美文网首页
JavaScript之this指向

JavaScript之this指向

作者: smaVivian | 来源:发表于2019-02-22 15:29 被阅读0次

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

this绑定规则:

  1. 默认绑定,this指向全局对象window,严格模式下指向undefined
function foo() {
    console.log( this.a );
}
var a = 2;
foo(); // 2
  1. 隐式绑定,由上下文对象调用?绑定到那个上下文对象。
function foo() {
    console.log( this.a );
}
var obj = {
    a: 2,
    foo: foo
};
obj.foo(); // 2
  1. 显示绑定,由 call 或者 apply (或者 bind )调用?绑定到指定的对象。
function foo(str1, str2) {
    console.log( this.a );
}
var obj = {
    a:2
};
foo.call( obj, 'aa', 'aa2' ); // 2
  • 硬绑定:一种显式的强制绑定,典型应用场景就是创建一个包裹函数,传入所有的参数并返回接收到的所有值
    function foo(something) {
        console.log( this.a, something );
        return this.a + something;
    }
    var obj = {
        a:2
    };
    var bar = function() {
        return foo.apply( obj, arguments );
    };
    var b = bar( 3 ); // 2 3
    console.log( b ); // 5
    
    硬绑定是一种常用的模式,ES5 中提供了内置的方法 Function.prototype.bind
    function foo(something) {
        console.log( this.a, something );
        return this.a + something;
    }
    var obj = {
        a:2
    };
    var bar = foo.bind( obj );
    var b = bar( 3 ); // 2 3
    console.log( b ); // 5
    
    为什么要在 new 中使用硬绑定函数呢?
    为了预先设置函数的一些参数,这样在使用new 进行初始化时就可以只传入其余的参数。 bind(..)可以对参数进行柯里化,就是可以把除了第一个参数(第一个参数用于绑定 this )之外的其他参数都传给下层的函数(这种技术称为“部分应用”,是“柯里化”的一种)
    function foo(p1,p2) {
        this.val = p1 + p2;
    }
    // 之所以使用 null 是因为在本例中我们并不关心硬绑定的 this 是什么
    // 反正使用 new 时 this 会被修改
    var bar = foo.bind( null, "p1" );
    var baz = new bar( "p2" );
    baz.val; // p1p2
    
    • API调用的“上下文”第三方库的许多函数,以及 JavaScript 语言和宿主环境中许多新的内置函数,都提供了一个可选的参数,通常被称为“上下文”(context),其作用和 bind(..) 一样,确保你的回调函数使用指定的 this 。
    function foo(el) {
        console.log( el, this.id );
    }
    var obj = {
        id: "awesome"
    };
    // 调用 foo(..) 时把 this 绑定到 obj
    [1, 2, 3].forEach( foo, obj );
    // 1 awesome 2 awesome 3 awesome
    
  1. new绑定,绑定到新创建的对象
function foo(a) {
    this.a = a;
}
var bar = new foo(2);
console.log( bar.a ); // 2

优先级: new绑定 -> 显示绑定 -> 隐式绑定 -> 默认绑定

被忽略的 this

如果函数并不关心 this 的话,你仍然需要传入一个占位值,这时 null 可能是一个不错的选择

function foo(a,b) {
    console.log( "a:" + a + ", b:" + b );
}
// 把数组“展开”成参数
foo.apply( null, [2, 3] ); // a:2, b:3
// 使用 bind(..) 进行柯里化
var bar = foo.bind( null, 2 );
bar( 3 ); // a:2, b:3

然而,总是使用 null 来忽略 this 绑定可能产生一些副作用。如果某个函数确实使用了this (比如第三方库中的一个函数),那默认绑定规则会把 this 绑定到全局对象(在浏览器中这个对象是 window ),这将导致不可预计的后果

优化:
Object.create(null) 和 {} 很像,但是并不会创建 Object.prototype 这个委托,所以它比 {} “更空”

function foo(a,b) {
    console.log( "a:" + a + ", b:" + b );
}
// 我们的 DMZ 空对象
var _null = Object.create( null );
// 把数组展开成参数
foo.apply( _null, [2, 3] ); // a:2, b:3
// 使用 bind(..) 进行柯里化
var bar = foo.bind( _null, 2 );
bar( 3 ); // a:2, b:3

this词法:ES6中的箭头函数

ES6中的箭头函数,箭头函数不使用 this 的四种标准规则,而是根据当前的词法作用域来决定this ,具体来说,箭头函数会继承外层函数调用的 this 绑定(无论 this 绑定到什么)。这其实和 ES6 之前代码中的 self = 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
bar.call( obj2 ); // 2, 不是 3 !  箭头函数的绑定无法被修改

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

箭头函数最常用于回调函数中,例如事件处理器或者定时器:
function foo() {
    setTimeout(() => {
    // 这里的 this 在此法上继承自 foo()
    console.log( this.a );
    },100);
}
var obj = {
    a:2
};
foo.call( obj ); // 2

相关文章

  • JavaScript之this指向

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

  • javascript this 指向

    我在文章《javascript 执行上下文》中介绍了 javascript 代码在执行时,会相应地创建对应执行上下...

  • javascript this指向

    首页,js默认的对象是Window,调用一个函数是,如果不去改变它的调用对象的话,this基本上都会指向Windo...

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

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

  • javaScript之this指向问题完全解析

    函数调用一般有以下三种情况:1.fun(p1,p2)2.obj.fun(p1,p2)3.fun.apply(thi...

  • JavaScript之彻底搞懂this的指向

    一、前言 this是JavaScript中的一个关键字,但是想要搞清楚它是怎么使用的,却不是那么的容易。this会...

  • JavaScript_this指向

    this的指向是在函数执行的时候确定的;同一个函数由于调用的方式不同,this的指向也会发生变化; this的几种...

  • JavaScript this的指向

    在 JavaScript 中 this 取什么值,是在函数真正被调用执行的时候确定的,函数定义的时候确定不了,因为...

  • JavaScript--this指向

    this存在的场景1)作为普通函数中的this2)使用call apply bind3)作为对象方法被调用4)在c...

  • JavaScript this指向总结

    JS中this的指向有些复杂,分为较多种的情况。此外,在严格模式和非严格模式之间也会有一些差别。 注:node环境...

网友评论

      本文标题:JavaScript之this指向

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