详解javascript中this属性
this总是返回一个对象,即返回属性或方法当前所在的对象。
对象的属性可以赋给另一个对象,所以属性所在的当前对象是可变的,即this的指向是可变的。
eg:
var A = { name : '张三', describe : function(){ return '姓名:' + this.name; } }; var B = { name : '李四' } B.describe = A.describe; B.describe();
结果:“姓名:李四”
再看一个例子:
var A = { name : '张三', describe : function(){ return '姓名:' + this.name; } }; var name = '李四' f = A.describe; f();
结果也是“姓名:李四”,因为这时this指向f运行时所在的对象——顶层window
this的使用场合
1、全局环境——无论this是不是在函数内部,只要是在全局环境下运行,this就是指顶层对象window
2、构造函数——指的是实例对象
eg:
var Obj = function(p){ this.p = p; } Obj.prototype.a = function(){ return this.p; } var obj = new Obj('color'); obj.a(); obj.p;
结果是都返回"color"
上面代码定义了一个构造函数Obj,由于this指向实例对象,所以在Obj中定义this.p,相当于定义实例对象有一个p属性,然后m方法可以返回这个p属性。
3、对象的方法
var obj = { foo : function(){ console.log(this); } }; obj.foo();//obj
只有直接在obj对象上调用foo方法,this才会指向obj,其他用法时,this都指向代码块当前所在的对象。
情况一:(obj.foo = obj.foo)()——window
情况二:(false || obj.foo)()——window
情况三:(1 , obj.foo)()——window
上述代码中,obj.foo先运算再执行,即使它的值没有变化,this也不再指向obj了
4、Node
在Node中,若在全局环境里,this指向global,模块环境中,this指向module.exports
this使用注意点
1、避免多层this
var o = { f1 : function(){ console.log(this); var f2 = function(){ console.log(this); }(); } } o.f1();
执行结果是:
{f1: ƒ}
Window {decodeURIComponent: ƒ, postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, …}
为什么f2中的this指向的是全局对象呢?因为上面那段代码的执行过程实际上是
var temp = function(){ console.log(this); }; var o = { f1 : function(){ console.log(this); var f2 = temp(); } } o.f1();
解决方法一——在第二层改用一个指向外层this的变量
var o = { f1 : function(){ console.log(this); var that = this; var f2 = function(){ console.log(that); }(); } } o.f1();
使用一个变量固定this的值,然后内层调用这个变量,是非常有用而且大量应用的方法
解决方法二——使用严格模式,在严格模式下,如果函数内部的this指向顶层对象就会报错。
2、避免数组处理方法中使用this
var o = { v : 'hello', p : ['a1','a2'], f : function(){ this.p.forEach(function(item){ console.log(this.v + ' ' + item); }); } } o.f();
结果:
undefined a1
undefined a2
导致这个结果的原因跟上一段的多层this是一样的
解决方法一——使用中间变量
var o = { v : 'hello', p : ['a1','a2'], f : function(){ var that = this; this.p.forEach(function(item){ console.log(that.v + ' ' + item); }); } } o.f();
解决方法二——将this当作forEach方法的第二个参数,固定它的运行环境
var o = { v : 'hello', p : ['a1','a2'], f : function(){ this.p.forEach(function(item){ console.log(this.v + ' ' + item); },this); } } o.f();
3、避免回调函数中的this
var o = new Object(); o.f = function(){ console.log(this === o); } o.f();//true $("#button").on("click",o.f);//false
绑定this的方法
JavaScript提供了call、apply、bind三个方法来切换/固定this的指向
function.prototype.call()
函数实例的call方法可以指定函数执行时this所在的作用域,call方法的参数量个对象,如果参数为空、null、undefined,则默认传入全局对象。如果call的参数不是对象,那么会被自动包装成包装对象。func.call(thisValue,arg1,arg2,……)
var n = 123; var obj = {n : 456}; function a(){ console.log(this.n); } a.call();//123 a.call(null);//123 a.call(undefined);//123 a.call(window);//123 a.call(obj);//456
call方法的一个应用是调用对象的原生方法
var obj = {}; //原生方法 obj.hasOwnProperty('toString');//false //覆盖了原生的方法 obj.hasOwnProperty = function(){ return true; } obj.hasOwnProperty('toString');//true //调回原生的方法 Object.prototype.hasOwnProperty.call(obj,'toString');//false
function.prototype.apply()
apply与call唯一的区别是apply接受一个数组作为函数执行时的参数,func.apply(thisValue,[arg1,arg2,……])
apply的应用之一——找出数组的最大元素
var a = [10,3,4,2]; Math.max.apply(null,a);
apply的应用之二——将数组的空元素变为undefined(因为数组的forEach方法会跳过空元素,却不会跳过undefined)?
var a = ['a','','b']; function print(i){ console.log(i); } a.forEach(print);//a b Array.apply(null,a).forEach(print);//a undefined b
运行结果跟上面不太一样,都是a b
apply的应用之三——转换类似数组的对象
Array.prototype.slice.apply({0:1,length:1});
apply的应用之四——绑定回调函数的对象
var o = new Object(); o.f = function(){ console.log(this === o); } var f = function(){ o.f.apply(o);//或o.f.call(o); } $("#button").on("click",f);
function.prototype.bind()
bind方法用于将函数体内的this绑定到某个对象,然后返回一个新函数
下面的例子在将方法赋值后会出错
var d = new Date(); d.getTime(); var print = d.getTime; print();//Uncaught TypeError: this is not a Date object.
解决方法:
var print = d.getTime.bind(d);
bind比call和apply更进一步的是,除了绑定this以外,还可以绑定原函数的参数
var add = function(x,y){ return x * this.m + y * this.n; } var obj = { m:2, n:2 } var newAdd = add.bind(obj,5);//绑定add的第一个参数x newAdd(5);//第二个参数y
对于那些不支持bind方法的老式浏览器,可以自行定义bind方法
if(!('bind' in Function.prototype)){ Function.prototype.bind = function(){ var fn = this; var context = arguments[0]; var args = Array.prototype.slice.call(arguments,1); return function(){ return fn.apply(context,args); } } }
以上就是详解javascript中this属性的详细内容,更多请关注其它相关文章!