欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

"this"和普通函数

程序员文章站 2022-03-02 14:14:01
...

以下内容 摘自https://www.w3cschool.cn/ivmkf/ivmkf-v3y2250z.html

https://classroom.udacity.com/nanodegrees/nd001-cn-preview/parts/63e29129-49ba-41cf-87d6-f98246da3f24/modules/166575d1-e43b-4cbf-90da-26c36c6b3c96/lessons/c867d0a9-1ee7-48ce-8275-e0dfb1cf013e/concepts/654cbc3e-5081-49e3-a17e-86198de93db6

https://classroom.udacity.com/nanodegrees/nd001-cn-preview/parts/63e29129-49ba-41cf-87d6-f98246da3f24/modules/166575d1-e43b-4cbf-90da-26c36c6b3c96/lessons/c867d0a9-1ee7-48ce-8275-e0dfb1cf013e/concepts/32f53f68-4b31-40fb-b136-4eda28b8ff57

要了解箭头函数中的 this 有何区别,让我们快速总结下标准函数中的 this 是如何使用的。如果你已经非常熟悉this 的使用方法,可以跳过此部分。

与我们常见的很多语言不同,JavaScript 函数中的 this 指向并不是在函数定义的时候确定的,而是在调用的时候确定的。换句话说,函数的调用方式决定了 this 指向

JavaScript 中,普通的函数调用方式有三种:直接调用方法调用和 new 调用。除此之外,还有一些特殊的调用方式,比如通过 bind() 将函数绑定到对象之后再进行调用通过 call()apply() 进行调用等。而 es6 引入了箭头函数之后,箭头函数调用时,其 this 指向又有所不同。下面就来分析这些情况下的 this 指向

直接调用

直接调用,就是通过 函数名(...) 这种方式调用。这时候,函数内部的 this 指向全局对象,在浏览器中全局对象是 window,在 NodeJs 中全局对象是 global

这里需要注意的一点是,直接调用并不是指在全局作用域下进行调用,在任何作用域下,直接通过 函数名(...) 来对函数进行调用的方式,都称为直接调用。

bind() 对直接调用的影响

还有一点需要注意的是 bind() 的影响。Function.prototype.bind() 的作用是将当前函数与指定的对象绑定,并返回一个新函数,这个新函数无论以什么样的方式调用,其 this 始终指向绑定的对象。

const obj = {};

function test() {

console.log(this === obj);}

const testObj = test.bind(obj);

test(); // false

testObj(); // true

call 和 apply 对 this 的影响

上面的示例中用到了 Function.prototype.apply(),与之类似的还有 Function.prototype.call()。这两方法的用法请大家自己通过链接去看文档。不过,它们的第一个参数都是指定函数运行时其中的 this 指向。

不过使用 apply 和 call 的时候仍然需要注意,如果目录函数本身是一个绑定了 this 对象的函数,那 apply 和 call 不会像预期那样执行

const obj = {};

function test() {
    console.log(this === obj);
}

// 绑定到一个新对象,而不是 obj
const testObj = test.bind({});
test.apply(obj);    // true

// 期望 this 是 obj,即输出 true
// 但是因为 testObj 绑定了不是 obj 的对象,所以会输出 false
testObj.apply(obj); // false

由此可见,bind() 对函数的影响是深远的,慎用!

方法调用

方法调用是指通过对象来调用其方法函数,它是 对象.方法函数(...) 这样的调用形式。这种情况下,函数中的 this 指向调用该方法的对象。但是,同样需要注意 bind() 的影响

方法中 this 指向全局对象的情况

注意这里说的是方法而不是方法调用中。方法中的 this 指向全局对象,如果不是因为 bind(),那就一定是因为不是用的方法调用方式,比如

const obj = {  

test() {  

console.log(this === obj);

}};

const t = obj.test;

t(); // false 这里就是相当于直接调用


t 就是 obj 的 test 方法,但是 t() 调用时,其中的 this 指向了全局。

箭头函数中的 this

箭头函数没有自己的 this 绑定。箭头函数中使用的 this,其实是直接包含它的那个函数或函数表达式中的 this

不管在什么情况下使用箭头函数,它本身是没有绑定 this 的,它用的是直接外层函数(即包含它的最近的一层函数或函数表达式)绑定的 this

示例中的两个 this 都是由箭头函数的直接外层函数(方法)决定的,而方法函数中的 this 是由其调用方式决定的。上例的调用方式都是方法调用,所以 this 都指向方法调用的对象,即 obj

箭头函数让大家在使用闭包的时候不需要太纠结 this,不需要通过像 _this 这样的局部变量来临时引用 this 给闭包函数使用。


this 关键字的价值完全取决于它的函数(或方法)是如何被调用的。this 可以是以下任何内容:


1. 新的对象

如果函数使用 new 被调用:

const mySundae = new Sundae('Chocolate', ['Sprinkles', 'Hot Fudge']);

在上述代码中,Sundae 这个构造函数内的 this 的值是新的对象,因为它使用 new 被调用。

2. 指定的对象

如果函数使用 call/apply 被调用:

const result = obj1.printName.call(obj2);

在上述代码中,printName() 中的 this 的值将指的是 obj2,因为 call() 的第一个参数明确设定 this 指代的是什么。

3. 上下文对象

如果函数是对象方法:

data.teleport();

在上述代码中,teleport() 中的 this 的值将指代 data

4. 全局对象或 undefined

如果函数被调用时没有上下文:

teleport();

在上述代码中,teleport() 中的 this 的值是全局对象,如果在严格模式下,是 undefined