梳理总结一下JS中常用又容易混淆的几个关键字---this
- 首先要明确,this总是返回一个对象(属性或方法的当前对象)。
//this.property,简单示例 var guy={ name:'atom', detail:function(){ alert('name:'+this.name) } } guy.detail();//name:atom,这是this返回当前对象的典型案例
由于属性可以赋值给另一个对象,所以属性所在的当前对象的this指向也是跟着改变的。
var A = { name: '张三', describe: function () { return '姓名:'+ this.name; } }; var B = { name: '李四' }; B.describe = A.describe; B.describe() // "姓名:李四"
同理:函数赋值给另一个变量,this指向跟着改变
var A = { name: '张三', describe: function () { return '姓名:'+ this.name; } }; var name = '李四'; var f = A.describe; f() // "姓名:李四" //原因,f的掉用点是window对象,而window对象含有一个name属性,故返回,如果没有声明name=‘李四’,则返回空;但显然不会返回’张三‘。
- 理解this,首先要理解JS中‘一切皆对象’的理念。运行环境也是对象,所有函数皆在某个对象之中运行,this即此对象。但JS中运行环境是动态的,这也就决定了this指向的动态性。
应用领域
- 全局中
this === window // true //或者 function f() { console.log(this === window); // true }
- 构造函数this指向(实例对象)
var Obj = function (p) { this.p = p; }; Obj.prototype.m = function() { return this.p; }; var o=new Obj('new'); o.m();//'new' o.p;//'new'
- 对象的方法:传递方法就传递指向
var obj ={ foo: function () { console.log(this); } }; obj.foo() // obj //在JS引擎中,obj和obj.foo储存在两个内存地址(L1,L2)L1,L2。只有obj.foo()调用时,从L1调用L2,因此this指向obj。 //当将方法赋值给另一个变量时,常得到意想不到的结果 var a = { b: { m: function() { console.log(this.p); }, p: 'Hello' } }; var hello = a.b.m; hello() // undefined
注意要点
- 避免多层嵌套
var o = { f1: function () { console.log(this); var f2 = function () { console.log(this); }(); } } o.f1();//Object,Window //实际执行以下代码 var temp = function () { console.log(this); };
var o = {
f1: function () {
console.log(this);
var f2 = temp();
}
}
//解决方案:that=this,使用一个变量固定this的值,然后内层函数调用这个变量,是非常常见的做法
var o = {
f1: function() {
console.log(this);
var that = this;
var f2 = function() {
console.log(that);
}();
}
}
o.f1()
// Object
// Object
//严格模式下,this指向顶层对象就会报错
- 避免数组中用
* 数组的map和foreach方法,允许提供一个函数作为参数。这个函数内部不应该使用this。
var o = {
v: 'hello',
p: [ 'a1', 'a2' ],
f: function f() {
this.p.forEach(function (item) {
console.log(this.v + ' ' + item);
});
}
}
o.f()
// undefined a1
// undefined a2
//内层this不指向外部----此时forEach回调函数中的this是指向window对象的
//同理解决
var o = {
v: 'hello',
p: [ 'a1', 'a2' ],
f: function f() {
var that = this;
this.p.forEach(function (item) {
console.log(that.v+' '+item);
});
}
}
o.f()
// hello a1
// hello a2
//或者,将this作为第二个参数,固定运行环境
var o = {
v: 'hello',
p: [ 'a1', 'a2' ],
f: function f() {
this.p.forEach(function (item) {
console.log(this.v + ' ' + item);
}, this);
}
}
o.f()
// hello a1
// hello a2
- 避免回调中用
var o = new Object();
o.f = function () {
console.log(this === o);
}
o.f() // true
//但这样,this就变了;而是指向了DOM对象
$('#button').on('click', o.f);
//解决方案如下:绑定this
//function.prototype.call()||apply()
var obj = {};
var f = function () {
return this;
};
f() === this // true
f.call(obj) === obj // true
//call||apply方法的参数是一个对象,如果为空,null,undefined则默认是全局对象
//call||apply调用原生方法
Object.prototype.hasOwnProperty.call(obj, 'toString') // false
//function.prototype.bind():用于将函数体内的this绑定到某个对象,然后返回一个新函数
var print = console.log;
print(2)
// TypeError: Illegal invocation,this指向不再是console对象了。解决方法:
var print = console.log.bind(console);
print(2)
// 2
> 总结一下,js中的this正如慕课网‘JS深入浅出’那节课所总结的那样----指向当前对象;想改变this指向主要有四种方法:隐式改变(new关键字)和显式改变(call,applay和bind方法),另外固化this也算是一种显式方法。
共同学习,写下你的评论
评论加载中...
作者其他优质文章