为了账号安全,请及时绑定邮箱和手机立即绑定

梳理总结一下JS中常用又容易混淆的几个关键字---this

标签:
JavaScript
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也算是一种显式方法。
点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
Web前端工程师
手记
粉丝
7244
获赞与收藏
3476

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消