此篇依然是读书笔记,内容自然是关于老生常谈的this指向问题,以及call和apply;
1.this的指向问题小结:
JavaScript的this总是指向一个对象,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境。
函数不作为对象的属性被调用时,也就是我们常说的普通函数方式,此时的this总是指向全局对象。在浏览器的JavaScript里,这个全局对象是window对象。
通常说来分为一下几种情况:
-
在
ECMAScript 5的strict模式下:- 这种情况下的
this已经被规定为不会指向全局对象,而是undefined
- 这种情况下的
-
当用
new运算符调用函数时:- 该函数总会
返回一个对象,通常情况下,构造器里的this就指向返回的这个对象
- 该函数总会
-
如果构造器显式地返回了一个
object类型的对象,那么此次运算结果最终会返回这个对象,而不是我们之前期待的this -
当用另外一个变量
getName2来引用obj.getName,并且调用getName2时,根据提到的规律,此时是普通函数调用方式,this是指向全局window的,所以程序的执行结果是undefined示例如下:var obj = { myName: 'kobe', getName: function(){ return this.myName; } }; console.log( obj.getName() ); // 输出:'kobe' var getName2 = obj.getName; console.log( getName2() ); // 输出:undefined
2.call和apply:
2.1 apply:
call和apply更多的作用像是一个金手指外挂,可以窃取自身不具有的能力。
apply接受2个参数,第1个参数指定了函数体内this对象的指向,第2个参数为一个带下标的集合,这个集合可以为数组,也可以为类数组
如果我们传入的第1个参数为null,函数体内的this会指向默认的宿主对象,在浏览器中则是window
//当使用call 或者apply 的时候,如果我们传入的第一个参数为null,函数体内的this 会指向默认的宿主对象,在浏览器中则是window:
var func = function( a, b, c ){
alert ( this === window ); // 输出true
};
func.apply( null, [ 1, 2, 3 ] );
Function.prototype.bind:用来指定函数内部的this指向,即使没有原生的Function.prototype.bind实现,我们来模拟一个也不是难事,代码如下:
Function.prototype.bind = function(){
var self = this, // 保存原函数
context = [].shift.call( arguments ), // 需要绑定的this 上下文
args = [].slice.call( arguments ); // 剩余的参数转成数组
return function(){ // 返回一个新的函数
return self.apply( context, [].concat.call( args, [].slice.call( arguments ) ) );
// 执行新的函数的时候,会把之前传入的context 当作新函数体内的this
// 并且组合两次分别传入的参数,作为新函数的参数
}
};
可以借用Array.prototype.push方法的对象还要满足以下两个条件:
- 对象本身要
可以存取属性 - 对象的
length属性可读写
一个number类型的数据不可能借用到Array.prototype. push方法:
var a = 1;
Array.prototype.push.call(a,'first');
alert(a.length);// undefined
一个函数当作this传入Array.prototype.push方法时:
var func = function(){};
Array.prototype.push.call( func, 'first' );
alert(func.lenght)//cannot assign to read only property ‘length' of function(){}
call的话,这里就不想过多的讲解了,除了和apply传参不一样,其他基本没差别。