bind,apply,call,caller,callee还傻傻分不清楚?
先介绍每个的语法: 1. bind() 语法:fn.bind(thisObj[,arg1[,arg2[,...]]]) fn:是想要改变this指向的函数 thisObj:表示fn中this指针指向的新对象。可选。 作用:改变this指向,并返回一个函数。 后面的参数:看似复杂,实际上就相当于一个一个列出来,即fn.bind(thisObj,arg1,arg2,...)。参数也可以为单独的数组,例如:fn.bind( thisObj,1,2,[3,34] );。可选 注意: 这个方式返回的是函数,并不像call和apply一样直接执行完成。要想执行必须后面再用 () 括号调用。这个方法在ie6-8不支持。并且ie9不支持严格模式。 ? bind()也可以这样使用: var newFn=fn.bind(thisObj); newFn(arg1,...); ? 这样每次调用newFn,这个函数里的this都是指向的是thisObj。 ? 2. apply() 语法:fn.apply(thisObj,[argsArray]) fn:是想要改变this指向的函数 thisObj:表示fn中this指针指向的新对象。可选 后面的参数:只能是一个数组。可选 注意:如果thisObj不指定或者thisObj为null或者undefined,那么thisObj默认为window对象。如果thisObj为字符串,数字,布尔值这些原始数据类型(这里不包括null和undefined)。那么此时的this会指向改原始数据类型包装的对象。例如: var obj={ say:function(){ console.log(this); } } obj.say.apply(‘123‘) 执行之后,this的值为: 其它的可以自行去举例体会。 ? 3. call() 语法:fn.call(thisObj,...) fn:是想要改变this指向的函数 thisObj:表示fn中this指针指向的新对象。可选 后面的参数:一个一个列出来。可选 注意:thisObj的注意事项和上面apply的一样。apply与call的区别就是接收的参数的区别,call是一个一个列出来,apply是一个数组。 ? 当参数确定时可以考虑用call,如果参数不确定时建议用apply。如果想多次使用改变this指针指向的函数,可考虑用bind 。 前三个方法的作用都是为了改变函数里this指针的指向。 关于不同情况下this指针指向,请看我的这篇文章:深入理解this指针指向。 ? 4. caller() 作用:返回调用指定函数的函数 语法:fn.caller() 注意:如果一个函数fn是在全局作用域内被调用的,则fn.caller为null。相反,如果一个函数fn是在另外一个函数作用域内被调用的,则fn.caller指向调用它的那个函数。而且caller只有在函数执行时才有效 ? ? 该特性是非标准特性,请尽量不要在生产环境中使用它。这是MDN上说的,但是caller被所有主流浏览器兼容 例子: function add(){ function bdd(){ console.log(bdd.caller) } bdd(); ? ? 最后输出的结果是: 因为add这个函数是在全局作用于内被调用,所以是null,而bdd是在add函数中被调用,所以是整个add函数。 ? 上面四个都是继承至Function。 下面的callee是函数参数集合arguments里的一个属性 ? 5. callee 作用:用于引用该函数的函数体内当前正在执行的函数 语法:arguments.callee 注意:在es5的严格模式下arguments.callee被删除了。但是普通模式下兼容性挺好的。 ?例子: function add(){ function bdd(){ console.log(arguments.callee) } bdd(); console.log(arguments.callee) } add() 结果分别是: 第一个console中,当前正在执行的函数是bdd,所以显示出来是bdd函数。第二个console,当前正在执行的是add,所以是add函数。 ? ? 下面是例子: call、apply: var obj = {age:10}; function fn() { console.log(this); console.log(this.age); } fn(); fn.call(obj); 来分析一下: (1) 当执行到fn()时,fn是window直接调用,是全局函数,所以此时this指向的是window。因此this.age是undefined (2) 当执行到fn.call(obj)时,call改变了fn函数中this的指向,此时this指向了obj,所以此时this.age是10; (3) 这里apply和call没区别,所以结果也是一样。 ? call、apply妙用: (1) 求数组中的最大,最小值(number类型) var num=[8,99,46,13,12,11,19,26]; var max=Math.max.apply(null,num);//99 var min=Math.min.apply(null,num);//1 ?(2) 类似数组的contact方法: var arr1 = ["a","777","b","c"]; var arr2 = ["n","m",77]; Array.prototype.push.apply(arr1,arr2); console.log(arr1);//["a","c","n",77] ? 再来一道简单的面试题: var name = "The Window"; var object = { name : "My Object",getNameFunc : function(){ console.log(‘1.‘ + this.name);//第一个console return function(){ return this.name; }; } }; var func = object.getNameFunc(); console.log(‘2.‘ + func());//第二个console console.log(‘3.‘ + func.call(object));//第三个console console.log(‘4.‘ + func.apply(object));//第四个console ??我们来分析一下这道题: (1) 当执行到?var func = object.getNameFunc();?这句代码时,会执行第一个console,这时候,getNameFunc()函数由于是通过object直接调用,那么这个函数中的this就是指向的object,所以第一个console输出的是? 1. My? Object? ?。然后这个函数返回了一个匿名函数。 (2) 当执行到第二个console时,由于上一句执行完之后,func是一个function,但还未执行,this指向不明确。这时候执行这个函数时,func是通过window直接调用,所以,此时func函数中的this指向的是window。所以第二个语句的输出是 2. The? Window。 (3) 执行到第三个console时,本来func中的this是指向window,但是通过call,改变了这个this的指向,call(object)告诉我们这时候,this指向的是object。所以第三个console输出的是? 3. My? Object (4) 由于call和apply只有传入参数的区别,所以这里的call和apply是一样的效果,所以这里func这里的this指向的还是object。所以第四个console输出的是? 4. My? Object ? bind: var a ={ name : "bajie",fn : function (a,b) { ?又来分析分析: (1)当执行到?var b = a.fn.bind(a);?的时候,这时的b就是通过bind函数返回的一个函数,而且这时b函数里的this指向的是a这个对象。 (2) 当调用b函数时,这时有人可能会说直接调用b的是window,所以这时this应该指向window。但是实际上,b函数里的this已经通过bind修改成指向a了,所以这里不管执行多少次,this都还是指向a。所以最终执行后结果是bajie? ?3; (3) 这里b函数也可以使用?window.b(1,2);?这样使用,结果还是一样的。使用了bind()之后并没有受到window的影响!!!这里需要注意。。。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |