资讯专栏INFORMATION COLUMN

JavaScript 中 this 的指向问题

DTeam / 2370人阅读

摘要:首发个人博客中的,大家都用过。箭头函数,词法作用域中的简单的说,箭头函数中的,会绑定到函数外也就是上一层作用域中的,函数外的指向哪,箭头函数中的就指向哪。

首发个人博客

JavaScript 中的 this ,大家都用过。但是它到底指向哪里呢?今天在阅读 《你不知道的JavaScript (上卷)》再结合自己平时看的博客,对它又有了新的认识,在此来做个小结,再碰到 this ,就再也不用担心不知道它指向哪里了。
与调用位置有关,而与定义位置无关

以下示例(在浏览器端运行)

function sayHi(){
    var hi = 1;
    console.log(this.hi);
}

var hi = 2;

var obj = {
    hi : 3,
    sayHi : sayHi
}

// output
sayHi(); // 2
obj.sayHi(); // 3

从上述代码的执行结果我们可以看出,直接调用 sayHi() 函数,它输出的 this.hi 不指向函数体内自己定义的 hi 变量,也就是说,this 的指向与词法作用域无关,这也是刚接触 JavaScript的同学常犯的一个错误(包括我自己),认为 this.xx 就指向函数体里面定义的变量 xxsayHi函数的只定义了一次,但obj.sayHi()sayHi() 的输出结果不一样,也恰恰证明了 函数体内this的指向与函数定义的位置无关,而与函数被调用的位置有关,至于为什么输出结果不一样,在下文会讲到。

this 的绑定规则 默认绑定

默认绑定比较常见,表现形式就是在全局作用域中独立调用,如上文中的 sayHi(),这种直接调用方式函数体内的 this 就应用了默认绑定规则,默认绑定有以下两种情况。

在严格模式下(指在函数声明的过程中,处在严格模式,而不是函数调用处于严格模式),函数体内 this 绑定到 undefined

在非严格模式下,函数体内 this 指向全局对象 window

/***** 以下例子为处在严格模式下 *****/
function fn1(){
    "use strict"
    console.log(this);
}

fn1(); // undefined

/***** 以下例子处于非严格模式下被调用 *****/
function fn2(){
    console.log(this);
}

fn2(); // window

function fn3(){
    console.log(this);
}

/*
 * 这也是在非严格模式下被调用
 * 因为在函数定义时没有用严格模式
 */
"use strict"
fn3(); // window
隐式绑定

隐式绑定的常见形式为 obj.fn(),若obj对象中有 fn 这个方法(fn可以在别处定义,但必须被添加到obj中作为obj的一个属性方法),那么 fn 中的 this 就指向 obj 对象,如最开始代码中 obj.sayHi() 输出3,就是因为sayHi中的this隐式绑定到obj对象。(个人觉得默认绑定中绑定到window对象时也可以归类为隐式绑定,因为在全局对象中,非严格模式且不考虑ES6的话,所有的全局变量都自动成为window的属性)。来看个具有迷惑性的例子(出自于原书)

function foo() { 
 console.log( this.a );
}
var obj = { 
 a: 2,
 foo: foo 
};
var bar = obj.foo; // 函数别名!
var a = "oops, global"; // a 是全局对象的属性
bar(); // "oops, global"

这是个具有迷惑性的例子,obj 对象有函数 foo 这个方法,后面又在全局作用域中,bar 引用了这个方法,最后再调用 bar。我们只需要关注函数最后被调用的位置,它是在全局作用域中被多带带调用的,所以还是为默认绑定,指向 window

显式绑定

显示绑定就比较简单了,用 call,apply,bind方法,都会绑定函数中的this到传入的参数对象中

new 绑定

所谓new绑定就是在用构造函数new一个对象的时候,其中的this指向生成的对象。这就完了嘛?还没有哦。

箭头函数,词法作用域中的this

简单的说,箭头函数中的this,会绑定到函数外(也就是上一层作用域中的this),函数外的this指向哪,箭头函数中的this就指向哪。(代码出自于原书)

function foo() {
    // 返回一个箭头函数
    return (a) => {
        //this 继承自 foo()
        console.log( this.a ); 
    };
}

var obj1 = { 
    a:2
};

var obj2 = { 
    a:3
};

var bar = foo.call( obj1 );
/*
 * foo先绑定this到obj1对象上,所以foo内的this指向obj1,
 * 返回的箭头函数根据词法作用域规则,继承了外部foo的this,
 * 所以箭头函数中的this指向obj1
 */


bar.call( obj2 ); // 2, 不是 3 !
/*
 * 箭头函数中this一但绑定,不可更改
 * 此时还是指向obj1
 * 所以输出的是 obj1.a => 2
 */
绑定的优先级

new > 显示 > 隐式 > 默认

上述知识来自《你不知道的JavaScript(上卷)》

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/98320.html

相关文章

  • JavaScriptthis 指向问题

    摘要:一等公民对象函数在提指向问题之前,肯定是有必要说明一等公民对象,既然是对象,那么就能像普通的值一样传递。在普通浏览器中指向的是在中指向的是全局对象全局环境中或者模块环境中。即指向或者的第一个参数。第二条规则,指向的不是原文链接 1. 一等公民对象——函数 在提this指向问题之前,肯定是有必要说明一等公民对象function ,既然function是对象,那么就能像普通的值一样传递。嗯...

    Alan 评论0 收藏0
  • 我对JavaScriptthis一些理解

    摘要:匿名函数的执行环境具有全局性,因此它的对象通常指向。如果对此有疑惑,可以看知乎上的答案知乎匿名函数的指向为什么是作为对象方法的调用,指向该对象当函数作为某个对象的方法调用时,就指这个函数所在的对象。 因为日常工作中经常使用到this,而且在JavaScript中this的指向问题也很容易让人混淆一部分知识。 这段时间翻阅了一些书籍也查阅了网上一些资料然后结合自己的经验,为了能让自...

    focusj 评论0 收藏0
  • 关于javascript 高级定时器若干问题

    摘要:闭包闭包是指有权访问另一个函数作用域中的变量的函数当某个函数被调用时,会创建一个执行环境及相应的作用域链。要注意通过第句声明的这个方法属于构造函数生成的对象,而不属于构造函数的变量对象,也就是说,并不存在于作用域链中。 看到评论里有仁兄建议我试试箭头函数,真是受宠若惊,本来写这篇文章也只是想记录写要点给自己日后看的。今天早上看到一篇总结javascript中this的文章JavaScr...

    zr_hebo 评论0 收藏0
  • JavaScript this 指向问题深度解析

    摘要:而改变了这种状态,虽然定义的类用运算符得到的仍然是,但它不能像普通函数一样直接调用同时,中定义的方法函数,也不能当作构造函数用来调用。而在中,用调用一个构造函数,会创建一个新对象,而其中的就指向这个新对象。 JavaScript 中的 this 指向问题有很多博客在解释,仍然有很多人问。上周我们的开发团队连续两个人遇到相关问题,所以我不得不将关于前端构建技术的交流会延长了半个时候讨论 ...

    liuchengxu 评论0 收藏0
  • 轻松搞定javascriptthis指向

    摘要:调用在中,通过的形式调用一个构造函数,会创建这个构造函数实例,而这个实例的指向创建的这个实例。如下例所示,在构造函数内部使用并没有改变全局变量的值。显然,箭头函数是不能用来做构造函数。   关于javascript中this指向的问题,现总结如下,如有不正确,欢迎指正。   javascript中,this的指向并不是在函数定义的时候确定的,而是在其被调用的时候确定的。也就是说,函数的...

    shinezejian 评论0 收藏0

发表评论

0条评论

DTeam

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<