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

理解JavaScript的this

标签:
JavaScript

this实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用。

function baz() {
    console.log('baz');
    bar();
    console.log('baz-end');
}

function bar() {
    console.log('bar');
    foo();
    console.log('bar-end');
}

function foo() {
    console.log('foo');
    console.log('foo-end');
}

baz();

// 理解栈调用:后进先出
// 输出顺序:baz -> bar -> foo -> food-end -> bar-end -> baz-end

第一条规则:在全局作用域下调用,this绑定的是全局window对象,如果在严格模式下,this绑定的是undefined

实例一:

var name = "bob";

function getName() {
    var name = "lynn";
    console.log(this); // this指向的是window对象
    console.log(this.name); //bob
}

getName();

实例二:

// 严格模式下

"use strict";
var name = "bob";

function getName() {
    var name = "lynn";
    console.log(this); // this指向的是 undefined 对象
    console.log(this.name); // TypeError Cannot read property 'name' of undefined
}

getName();

实例三:

var name = "lynn";

function getName() {
    console.log(this.name);
}


var obj1 = {
    name: 'peter',
    getName: getName
}

var getUserName = obj1.getName;
getUserName(); // 输出:lynn,this指向的是全局对象
// 原因:getUserName实际上是保存着是getName函数的指针,调用的环境是全局对象

实例四:

var name = "lynn";

function getName() {
    console.log(this.name);
}

function getUserInfo(fn) {
    // fn 
    fn()
}

var obj1 = {
    name: 'bob',
    getName: getName
}

getUserInfo(obj1.getName) // lynn
// 同样getUserInfo调用的环境是全局对象中,this绑定的是全局对象

第二条规则:调用位置是否有上下文对象,如果包含多个对象引用链,那this指向是最后一个上下文对象。

实例一:全局下调用函数 与 对象中的调用函数

var name = "lynn"
function getName() {
    console.log(this.name);
}

var obj1 = {
    name: 'bob',
    getName: getName
}
getName(); // 输出:lynn, this指向的是全局对象
obj1.getName(); // 输出:bob, this绑定的是 o 对象

实例二:多个对象嵌套调用时,取决于最后一个对象的绑定

var name = "lynn"

function getName() {
    console.log(this.name);
}

var obj2 = {
    name: 'peter',
    getName: getName
}

var obj1 = {
    name: 'bob',
    obj2: obj2
}

obj1.obj2.getName(); // 输出:peter,this绑定的是 obj2 对象

第三条规则:是否是否call(),apply(),bind()方法显式绑定,如果是的话,this绑定的是指定的对象

实例一:call绑定

var name = "bob";
var o = {name: "lynn"};

function getName() {
    console.log(this.name);
}

getName.call(o); // 输出:lynn,this绑定的是 o 对象

实例二:apply绑定

var name = "bob";
var o = {name: "lynn"};

function getName() {
    console.log(this.name); 
}

getName.apply(o); // 输出:lynn,this绑定的是 o 对象

实例三:bind绑定

var name = "bob";
var o = {name: "lynn"};

function getName() {
    console.log(this.name);
}

var getUserInfo = getName.bind(o);
getUserInfo();  // 输出:lynn this绑定的是 o 对象

第四条规则:函数是否被new调用,如果是的话this绑定的是新创建的对象。

function Person(name) {
    this.name = name;
}
let person = new Person("bob");
console.log(person.name);

第五条规则:ES6箭头函数不会使用前面4条规则,是根据当前此法作用域来决定this,箭头函数会继承外层函数调用的this绑定。

var name = "bob";

var o = {name: 'lynn'};

function getName() {
    return () => {
        console.log(this.name);
    }
}

getName()(); // 输出:bob 这时候绑定的是全局window对象

getName().call(o); 
// 输出:bob 
// 这时候在调用 箭头函数 使用call改变绑定,
// 但 箭头函数 会 继承外层函数 调用的this绑定,
// 但这时候绑定的仍然是 外层函数 的this绑定的对象,即全局window对象。

getName.call(o)(); 
// 输出:lynn 
// 在调用箭头函数之前,箭头函数 的 外层函数 改变this绑定o对象,
// 箭头函数 会继承 外层函数的this绑定,this指向的是o对象
点击查看更多内容
6人点赞

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

评论

作者其他优质文章

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

关注作者,订阅最新文章

阅读免费教程

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

100积分直接送

付费专栏免费学

大额优惠券免费领

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

举报

0/150
提交
取消