码迷,mamicode.com
首页 > 编程语言 > 详细

《Javascript权威指南》函数

时间:2015-04-02 01:16:03      阅读:191      评论:0      收藏:0      [点我收藏+]

标签:

一、函数定义

函数声明语句声明了一个变量,并把一个函数对象赋值给它。定义函数表达式没有声明变量。

如果一个函数定义表达式包含名称,函数的局部作用域会包含一个绑定到函数对象的名称。函数的名称成为函数内部的局部变量。

函数声明语句“被提前”到外部脚本或外部函数作用域顶部,可以在它定义前出现的代码调用。但表达式定义的函数不能。

 

二、函数调用

1.函数调用

如果函数表达式是一个属性访问表达式,即该函数是一个对象的属性或数组的一个元素,则它是方法调用表达式

 

2.方法调用

o.m();

对象o成为调用上下文,函数体可以使用this引用该读写

当方法返回值是一个对象,它还可以再调用它的方法。当方法不需要返回值,最好返回this。

this是关键字,不允许给this赋值。this没有作用域的限制,嵌套的函数不会从调用它的函数继承this。如果嵌套函数作为方法调用,其this值指向调用它的对象。如果嵌套函数作为函数调用,其this值不少全局对象(非严格模式下)就是undefined(严格模式下)。如果想访问外部函数的this值,需要将this保存在一个变量里,这个变量和内部函数都在同一个作用域。通常用变量self保存this。

 

var o = {
    m: function() {
        var self = this;
        console.log(this === o);         //true
        f();

        function f() {                         //嵌套函数f()
            console.log(this === o);    //false
            console.log(self === o);    //true
        }
    }
};    

 

3.构造函数调用

 如果构造函数没有形参,可以省略实参列表和圆括号。

 构造函数调用创建新的对象,对象继承自构造函数的prototype属性,将这儿对象当做其调用上下文。

 

4.间接调用

call() apply()

 

作为命名空间的函数

定义一个函数作为临时的命名空间,其中定义的变量不会污染到全局命名空间。

// 因为想下面第一个声明的function可以在后面加一个括弧()就可以自己执行了,比如foo(),
// 因为foo仅仅是function() { /* code */ }这个表达式的一个引用
 
var foo = function(){ /* code */ } ()

//解析器解析全局的function或者function内部function关键字的时候,默认是认为function声明,而不是function表达式,
//如果你不显示告诉编译器,它默认会声明成一个缺少名字的function,并且抛出一个语法错误信息,因为function声明需要一个名字。
function(){ /* code */ }(); // SyntaxError: Unexpected token

我们只需要用大括弧将代码的代码全部括住就行了,因为JavaScript里括弧()里面不能包含语句。

所以在这一点上,解析器在解析function关键字的时候,会将相应的代码解析成function表达式,而不是function声明。

// 下面2个括弧()都会立即执行

(function () { /* code */ } ()); // 推荐使用这个
(function () { /* code */ })(); // 但是这个也是可以用的

 

 

 

定义一个匿名函数,在单个表达式中调用它。

(function() {
    //代码
}());

function之前的左圆括号是必须的,如果不写会将function姐希望函数声明语句。使用圆括号被解析为函数定义表达式

 

闭包

函数对象可以通过作用域链相互关联,函数体内部的变量都可以保存在函数作用域内,这种特性成为闭包。

//返回 function f() {return a;}
var a = ‘global‘;
function check() {
    var a = ‘local‘;
    function f() {return a;}
    return f;
}
check()

 

闭包可以捕捉到局部变量(和参数),并一直保存。

//check()只返回函数内嵌套的一个函数对象,而不是直接返回结果。
//返回 local scope
var a = ‘global‘; function check() { var a = ‘local‘; function f() {return a;} return f; } check()()

 

每次调用javascript函数时,都会为之创建一个新对象来保存局部变量,把这个对象添加到作用域链。当函数返回时,从作用域链中将这个绑定变量的对象删除。如果不存在嵌套的函数,也没有其他引用指向这个绑定对象,它会被当做垃圾处理。 如果定义了嵌套函数,每个嵌套的函数都各自对应一个作用域链,并且这个作用域链指向一个变量绑定对象。

如果这个函数定义了嵌套的函数并将它作为返回值返回或存储在某处的属性里,这时就会有一个外部引用指向这个嵌套的函数,它和它指向的变量绑定对象都不会被当做垃圾回收。

 

//定义了一个立即调用的函数,函数的返回值赋值给a
//外部函数返回后,其他代码无法访问count变量
var uniqueInteger = (function() {
                        var count = 0;
                        return function() {return count++};
                    }());

uniqueInteger            //函数对象
uniqueInteger()          //0
uniqueInteger()()        //1

 

//返回一个总是返回v的函数
function constfuncs(v) { return function() { return v;}; }
var funcs = [];
for (var i = 0; i < 10; i++) funcs[i] = constfuncs(i);
alert(funcs[5]()) //5


//这些闭包都在同一个函数调用定义,可以共享变量i
function constfuncs() {
    var funcs = [];
    for (var i = 0; i < 10; i++)
        funcs[i] = function() { return i; };
    return funcs;
}
var funcs = constfuncs();
alert(funcs[5]())   //10

 

函数属性、方法和构造函数

length属性

prototype属性

call() apply() 方法

bind()方法 将函数绑定到某个对象

toString()方法

 

Function()构造函数

可以传入任意数量的字符串参数,最后一个参数的文本是函数体。

不需要传入函数名

函数体代码的编译总在顶层函数执行,可以认为是在全局作用域执行的eval()

var scope = "global";
function constructFunction() {
    var scope = "local";
    return new Function("return scope");
}
//返回global,因为通过Function()构造函数返回的函数使用的不是局部作用域
constructFunction()()

 

《Javascript权威指南》函数

标签:

原文地址:http://www.cnblogs.com/surahe/p/4375900.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!