此篇依然是读书笔记,内容自然是关于老生常谈的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
传参不一样,其他基本没差别。