美文网首页JavaScript 进阶营让前端飞
js中关于this全面解析和this的指向问题

js中关于this全面解析和this的指向问题

作者: 绿芽 | 来源:发表于2021-08-18 15:30 被阅读0次

this指向原则
每个函数的this是在调用的时候被绑定的,完全取决于函数的调用位置。

1、 调用位置

调用位置就是函数在代码中被调用的位置(而不是声明的位置)。要找到调用位置就要分析调用栈(就是为了达到当前执行位置所调用的所有函数),我们要找的调用位置就在当前正在执行的函数的前一个调用中。如以下代码:

function baz() {
    // 当前的调用栈是baz
    // 当前的调用位置是全局作用域
    console.log(‘baz’);
    bar(); // bar的调用位置
}
function bar() {
    // 当前的调用栈 window  baz  bar
    // 因此,当前调用位置在 baz 中 
    foo(); // foo的调用位置
}
function foo () {
    // 当前的调用栈是 window –> baz  bar  foo
    // 所以foo函数的当前调用位置在bar中
    Console.log('foo');le.log(‘foo’);
}
baz(); // <-- baz 的调用位置 

2、绑定规则

(1)默认绑定
直接独立调用的函数this指向就使用的了默认绑定规则直接指向全局作用域如下代码:

function foo() {
    console.log( this.a ); 
} 
    var a = 2; 
foo(); // 2 

foo()函数是直接使用不带任何修饰的函数引用进行调用的,因此使用默认绑定规则。
(注意: 默认绑定规则在非严格模式下指向window,而在严格模式下的时候就会指向undefined)

(2)隐士绑定
隐士绑定规则要看调用位置是否有上下文对象,也就是说看函数是否被某个对象拥有或者引用。代码如下所示:

function foo() { 
    console.log( this.a ); 
} 
var obj2 = { 
    a: 42, 
    foo: foo
}; 
var obj1 = { 
    a: 2, 
    obj2: obj2 
}; 
obj1.obj2.foo(); // 42 

上述代码,虽然函数的声明位置在全局作用域中,但是而后被当做引用属性添加到了obj2中,(不管是直接在obj中定义还是先定义在添加为引用属性,这个函数严格意义来说都不属于obj2), 但是函数被调用的时候使用的是obj2的上下文引用,这个时候就触发了隐士绑定规则,当函数调用时,有引用的上下文对象时,隐士绑定规则就把
函数的this指向了这个上下文对象。
(注意:对象属性引用链中只有最顶层或者说最后一层会影响调用位置 )

(3)显示绑定
JavaScript 提供的绝大多数函数以及你自 己创建的所有函数都可以使用 call(..) 和 apply(..) ,bind()方法,使用这个方法会调用当前函数,并把this指向指定对象,这种绑定方式称为显示绑定。代码如下:

function foo() { 
    console.log( this.a)
} 
var obj = {
    a: 2
}
foo.call(obj); // 2

(4)new绑定
使用new来调用函数,或者说发生构造函数调用时,会执行下面操作
1> 创建(或者说构造)一个全新的对象
2> 这个新对象会被执行【原型】连接
3> 这个新对象会被绑定到函数调用的this
4> 如果函数没有返回其他的对象,那么new表达式中的函数调用会自动返回这个新对象。

判断this的指向

根据规则判断函数在调用的时候this的指向:
1> 函数是否在new中调用(new绑定)?如果是的话this绑定的是新创建的对象。

  var bar = new foo()

2> 函数是否通过call、apply(显式绑定)或者硬绑定调用?如果是的话,this绑定的是 指定的对象。

var bar = foo.call(obj2) 

3> 函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this 绑定的是那个上 下文对象。

var bar = obj1.foo() 

4> 如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到undefined,否则绑定到 全局对象。

var bar = foo()

绑定例外

如果你把 null 或者 undefined 作为 this 的绑定对象传入 call、apply 或者 bind,这些值 在调用时会被忽略,实际应用的是默认绑定规则:

function foo() { 
    console.log( this.a ); 
}
var a = 2;
foo.call( null ); // 2 

箭头函数

箭头函数是es6中的新语法,它不使用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 ); 
bar.call( obj2 ); // 2, 不是 3 ! 

foo() 内部创建的箭头函数会捕获调用时 foo() 的 this。由于 foo() 的 this 绑定到 obj1, bar(引用箭头函数)的 this 也会绑定到 obj1,箭头函数的绑定无法被修改。(new 也不 行!)

相关文章

  • js中关于this全面解析和this的指向问题

    this指向原则每个函数的this是在调用的时候被绑定的,完全取决于函数的调用位置。 1、 调用位置 调用位...

  • 关于js函数中this的指向的问题

    @(javascript)[JavaScript中this的指向] 关于js函数中this的指向的问题 javas...

  • JS中关于this的指向问题

    如果一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window var user 只...

  • JavaScript经典面试题(2)--this指向及应用

    关于js中的this指向问题:有很多同学刚接触js时,对this的指向问题很是迷惑,在有些不常见情况,往往搞不...

  • JS进阶篇-this指向问题

    JS中this的指向问题不同于其他语言,JS中的this不是指向定义它的位置,而是在哪里调用它就指向哪里。 JS中...

  • js中this指向问题

    this的指向在函数定义的时候是无法确定的,只有函数执行的时候才能确定this到底指向谁,实际this指向是调用他...

  • JS中this指向问题

    首先声明,添加删除线的都是不太确定的 下面我们分情况解释: 1、函数调用模式--当一个函数并非一个对象的属性时,那...

  • js中this指向问题?

    This是一个关键字,它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用。 this 是在函数被调用时确...

  • js中this的指向问题

    this是Javascript语言的一个关键字它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用,下面分...

  • js 中 this 的指向问题

网友评论

    本文标题:js中关于this全面解析和this的指向问题

    本文链接:https://www.haomeiwen.com/subject/kyvgbltx.html