函数 - Javascript语法基本 - Javascript中心

原文: http://pij.robinqu.me/JavaScript_Core/JavaScript_Basics/Function.html

源代码: https://github.com/RobinQu/Programing-In-Javascript/blob/master/chapters/JavaScript_Core/JavaScript_Basics/Function.md

本文存在讲明,但该网站的Markdown编辑器不支撑,所以没法一般展现,请到原文参考。

函数

Javascript中,要记着函数是first-class citizen。

定义

  • 函数声明语句

    function plus(x ,y) {
    
    }
    
  • 函数定义表达式

    var plus = function (x, y) {
    
    }
    

函数挪用

  • 作为函数挪用

    function a(){};
    a();
    
  • 作为要领挪用

    a={};
    a.x = function(){};
    a.x();
    
  • 经由过程call和apply间接挪用函数(转变this)

call 和 apply带有多个参数,call和apply把当前函数的this指向第一个参数给定的函数或对象中,并通报其他一切的参数作为当前函数的参数。

var O = function () {
    this.foo  = 'hello';
    this.hello = function () {
        return 'world';
    }
};

var fn = function () {
    console.log('call', this);
};

var o = new O();

fn.call(o);//此时fn的this指向o

call和apply的差别之处,在于call通报的参数是作为arguments顺次传入的,比方

fn.call(o, 1, 2, 3);
而apply通报的参数是以一个数组的体式格局传入的,比方
fn.apply(o, [1, 2, 3]);

参数

当传入参数少于函数声明的参数时,留空的参数的值是undefined

Javascript许可传入参数的个数大于声明时制订的参数个数。能够用arguments来访问这些参数

function f(){
    var i;
    for( i = 0; i < arguments.length ; i++) {
        console.log(arguments[i]);
    }
}

f(1,2,3,4,5,6);

函数经由过程取得arguments的长度取得传入参数的个数,运用一个轮回猎取每一个参数。

arguments另有两个属性,calleecaller
callee示意正在实行的function对象,
caller示意挪用当前function的function

比方

function f(){
    console.log(arguments.callee);//[Function: f]
    console.log(arguments.callee.caller);[Function: g]
    var i;
    for( i = 0; i < arguments.length ; i++) {
        console.log(arguments[i]);
    }
}

function g(){
    f(1,2,3,4,5,6);
}

g();

callee 的主要用法之一是在匿名函数中完成递归

var result = function (x) {
    if (x <= 1) return 1;
    return x * arguments.callee(x - 1);
}(3);

console.log(result);

上例运用了一个匿名函数和callee完成了一个阶乘。

作为值的函数

javascript中的函数能够作为值来通报

function square(x) {
    return x * x;
}

var s = square;
s(4);

作为定名空间的函数

(function() {

}());

闭包

Javascript函数对象的内部状况不仅包含着函数的代码逻辑,还援用当前的作用域链。函数对象经由过程作用域链互相关联起来,函数体内部变量包含在函数作用域内,这就叫闭包。

比方

var scope = 'global scope';
function checkscope() {
    var scope = 'local scope';
    function f() { 
        return scope;
    }
    return f;
}

checkscope()();

这段checkscope声清楚明了一个局部变量,定义了一个函数f,函数f返回了这个局部变量的值,末了返回了这个函数f。在定义函数f的作用域外挪用f,取得的返回仍然是函数f建立时地点的作用域的局部变量scope。

又比方

var counter = (function() {
    var count = 0;
    return function () {
        return count++ ;
    }
}());

代码定义了一个马上实行函数并返回给counter,这个函数定义了一个局部变量count,返回了一个子函数,该子函数每次挪用,都邑吧count加一并返回。

闭包的注意事项

视察下面的示例:

var add_the_handlers = function (nodes) {
    var i;
        for (i = 0; i < nodes.length; i += 1) {
            nodes[i].onclick = function (e) {
                alert(i);
            };
        }
};

这个函数希冀的效果,是在运转的时刻为每一个node在onclick的时刻alert出各自的序号,然则现实运转的效果却差别:一切的node在单击的时刻alert出来的数字老是同一个。

这是由于alert地点的匿名函数的闭包中寄存的i是第一行的i,而不是在轮回中取得的i的当前值。

所以假如愿望到达预期效果,应该在轮回中建立多个闭包,在闭包中寄存当前轮回的i的值:

var add_the_handlers = function (nodes) {
    var i;
        for (i = 0; i < nodes.length; i += 1) {
            nodes[i].onclick = function (i) {
                return function(e){
                    alert(e);
                };
            }(i);
        }
};

这里运用一个马上实行函数并通报当前的i的值,返回一个新天生的函数。在这个新天生的函数的闭包中就保留了当前的i的值。

函数中的this对象

在一个对象中的this一直援用当前对象,然则在函数中,特别是在闭包中,this有一些特别的行动。

函数中的this对象一直绑定在函数运转时的上下文环境上。所以在一般形式下挪用一个全局函数,this一直指向window(客户端),在严厉形式下挪用一个全局函数,this一直是undefined

示例

var name = "The Window";
var object = {
    name: "My Object",
    getNameFunc: function () {
        return function () {
            return this.name;
        };
    },
    getName : function () {
        return this.name;
    }
};

console.log(object.getNameFunc()());
console.log(object.getName());

getNameFunction()返回了一个匿名函数,这个匿名函数在挪用的时刻,上下文是window(浏览器中),所以在浏览器中输出的是the Window

而getName()挪用的时刻上下文是object,所以胜利输出object的name

实在以上代码中
object.getNameFunc()()
等效于
var fnc = object.getNameFunc();//这时刻的fnc已脱离了object对象
fnc();

所以假如想要getNameFunction()准确返回Object的Name,需要在返回的匿名函数的闭包中保留在函数声明时的this,

getNameFunc: function () {
        var that = this;
        return function () {
            return that.name;
        };
    },

如许就能够了。。

函数柯里化

函数柯里化是指,把接收多个参数的函数转换成接收一个单一参数的函数,而且返回接收余下的参数而且返回效果的新函数的手艺。

示例

var add1 = add.curry(1);
console.log(add1(2));

个中,add是接收两个参数的函数,add挪用了curry返回一个只接收一个参数的新函数,以后挪用add1便等效于挪用add(1, 2);

javascript并不原生支撑curry,能够用prototype来模仿

Function.prototype.curry = function () {
    var slice = Array.prototype.slice,
        args = slice.apply(arguments),
        that = this;
    return function () {
        return that.apply(null, args.concat(slice.apply(arguments)));
    };
};


function add(n1, n2) {
    return n1 + n2;
}

var add1 = add.curry(1);
console.log(add1(2));

curry建立了一个新函数,在新函数的闭包中保留了本来通报的参数。

函数的属性和要领

  • length 函数的length示意函数实参的数目,是只读的
  • prototype 指向一个该函数的原型对象的援用
  • toString 返回一个字符串
    原文作者:RobinQu
    原文地址: https://segmentfault.com/a/1190000000515140
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞