this
js 的 this 总是指向一个对象,而具体指向哪个对象是在 运行时基于函数的环境动态绑定 的,而非函数被声明时的环境
this 的指向
除去 with 和 eval 情况,this 的指向大致分为以下 4 种
- 作为对象的方法调用
- 作为普通函数调用
- 构造器调用
- call 和 apply 调用
-
作为 对象的方法 调用,this 指向该对象
var obj = { a:1, getA:function(){alert:(this === obj)// 输出 true alert:(this.a)// 输出 1 } }
-
作为普通函数调用,此时 this 指向全局,如在浏览器中指向 window 对象
window.name = 'globalName' var myObject = { name:'obj', getName:function(){console.log(this.name) } } var getName = myObject.getName getName() // 输出 globalName,即全局。
- 构造器调用: 通常情况下,构造器里的 this 指向 new 返回的对象
如果构造器显式的返回一个 object 对象,this 会指向显式返回的对象
- call 与 apply,可以动态地改变传入函数的 this。call 和 apply 很好的体现了 js 的函数式语言特性。
call 和 apply 的区别
- apply 和 call 接收的第一个参数都指定函数体内 this 的指向。
- 第二个参数,apply 接收一个数组或类数组,call 从第二个参数开始,每个参数都被依次传入函数作为参数。
- 如果第一个参数为 null,函数体内的 this 指向默认的宿主对象,即 window 等
-
有时候我们使用 call 或者 apply 的目的不在于指定 this 指向,而是另有用途,比如借用其他对象的方法。那么我们可以传入 null 来代替某个具体的对象:
Math.max.apply(null, [ 1, 2, 5, 3, 4] ) // 输出:5
call 和 apply 的用途
-
改变函数内部 this 的指向
在实际开发中,经常会遇到 this 指向被不经意改变的场景,比如有一个 div 节点,div 节点的 onclick 事件中的 this 本来是指向这个 div 的:
document.getElementById('div1').onclick = function(){alert( this.id); // 输出:div1 };
假如该事件函数中有一个内部函数 func,在事件内部调用 func 函数时,func 函数体内的 this 就指向了 window,而不是我们预期的 div,见如下代码:
document.getElementById('div1').onclick = function(){alert( this.id); // 输出:div1 var func = function(){alert ( this.id); // 输出:undefined } func();};
这时候我们用 call 来修正 func 函数内的 this,使其依然指向 div:
document.getElementById('div1').onclick = function(){var func = function(){alert ( this.id); // 输出:div1 } func.call(this); };
- Function.prototype.bind: 用于指定函数内部 this 指向
-
借用其他对象的方法
-
借用构造函数,实现类似继承的效果
var A = function(name){this.name = name;}; var B = function(){A.apply( this, arguments); }; B.prototype.getName = function(){return this.name;}; var b = new B('sven'); console.log(b.getName() ); // 输出:'sven'
-
arguments 借用数数组的方法
在操作 arguments 的时候,我们经常非常频繁地找 Array.prototype.push 对象借用方法。
可以借用 Array.prototype 方法的对象需要满足以下两个条件
- 对象本身要可以存储属性
- 对象的 length 属性可读写
-