为什么要有this

1.为了让对象中的函数有能力访问对象自己的属性。

例子

如果我们想要在对象内部方法中使用对象内部的属性,就像图中的代码,它是可以在C语言里运行的,但是在JS中不可行,JS它需要使用this机制来访问(图中的myName)

 1let obj = {
 2    myName: '喜羊羊',
 3    age: 12,
 4    bar: function () { 
 5        console.log(this.myName);
 6    }
 7}
 8obj.bar();

2.this可以显著的提升代码质量,减少上下文参数的传递。

这种显示传参的方法有点啰嗦,如果我们采用this的话,那么就会优雅,方便很多。

 1function identify() {
 2    return this.name.toUpperCase();
 3}
 4
 5function speak() {
 6    var greeting = 'Hello, I am ' + identify.call(this);
 7    console.log(greeting);
 8}
 9
10var me = {
11    name: 'gg bond'
12}
13
14speak.call(me);

运行结果是一样的

this的使用场景

可以产生作用域的地方就可以用this(除了块级作用域)

也就是:

  1. 全局
  2. 函数体内
 1console.log(this);

在node里打印出来是:

因为node的全局是global空对象,跟浏览器的引擎有些不一样,我们看在浏览器上的运行:

全局代指的是Window

this 代指某一块作用域

写在全局下面就代指全局的作用域

this的绑定规则

1. 默认绑定

当一个函数直接独立调用,不带任何修饰符时,使用默认绑定。 - 函数在哪个词法作用域中生效,函数中的this就指向哪里。(只要是默认绑定this一定指向全局对象window。

 1function foo() {
 2    console.log(this);
 3}
 4foo();
 1function foo() {
 2    console.log(this);
 3}
 4function bar() {
 5    foo();
 6}
 7bar()

var

在全局,通过var声明的变量相当于window.xxx,在window对象上添加了一个属性在函数中,通过var声明的变量相当于函数的词法作用域。

let就不会

2. 隐式绑定

当函数的引用有上下文对象时(当函数被某个对象所拥有时),隐式绑定。 - 函数中的this指向的是引用它的对象。

 1var obj = {
 2  a: 1,
 3  foo: foo
 4}
 5
 6function foo() {
 7  console.log(this.a);
 8}
 9
10obj.foo()

3. 隐式丢失

当一个函数被赋值被多个对象链式调用时,函数的this指向就近的那个对象

 1我附庸的附庸不是我的附庸
 1var obj = {
 2  a: 1,
 3  foo: foo
 4}
 5
 6var obj2 = {
 7  a: 2,
 8  obj: obj
 9}
10
11function foo() {
12  console.log(this.a);
13}
14
15obj2.obj.foo()

4. 显示绑定

通过bind、apply、call,将函数的this指向指定的对象。call直接接受参数,apply接受参数需要用数组装起来。

bind()

band()会默认返回一个函数体。

当这个新函数被调用时,它的 this 值会被设置为在 bind() 调用中传递的第一个参数。

 1function greet(greeting) {
 2    console.log(greeting + ', ' + this.name);
 3}
 4
 5let person = { name: 'GG Bond' };
 6
 7let greetJohn = greet.bind(person, 'Hello'); 
 8greetJohn(); 

call()

立即调用一个函数,并允许指定 this 值以及任何需要传递给函数的参数。参数直接列在 call() 后面,不需要用数组包装。

 1function greet(greeting) {
 2    console.log(greeting + ', ' + this.name);
 3}
 4
 5let person = { name: 'call' };
 6
 7greet.call(person, 'Hi'); 

apply()

apply() 也立即调用一个函数,但与 call() 不同的是,它的参数需要以数组的形式给出。

 1var obj = {
 2    a: 1
 3}
 4
 5function foo(x, y) {      
 6    console.log(this.a, x + y);
 7}
 8foo.apply(obj, [1, 2])

6. new绑定

通过new调用函数,将函数的this指向新创建的对象。

创建对象并绑定 this 的过程:

  1. 创建一个新对象:首先,JavaScript 引擎会创建一个全新的空对象。
  2. 设置原型链:新对象的原型(__proto__)会被设置为构造函数的 prototype 属性所指向的对象。
  3. 绑定 this:函数内部的 this 被绑定到这个新创建的对象上。
  4. 执行构造函数:构造函数的代码被执行,this 指向新创建的对象。
  5. 返回新对象:如果构造函数没有显式返回一个对象,则默认返回新创建的对象。如果构造函数返回了一个对象,那么这个返回的对象将覆盖新创建的对象。
 1function Person(name) {
 2    this.name = name;
 3    return {}; 
 4}
 5let jane = new Person('Jane');
 6console.log(jane instanceof Object); 
 7console.log(jane instanceof Person); 
 8

7. 箭头函数

箭头函数中没有this这个机制,写在箭头函数中的this也是它外层非箭头函数的

 1function regularFunction() {
 2    console.log(this);
 3}
 4
 5
 6const arrowFunction = () => {
 7    console.log(this);
 8};
 9
10
11const obj = {
12    name: 'Test',
13    regularMethod: function() {
14        console.log(this);
15    },
16    arrowMethod: () => {
17        console.log(this);
18    }
19};
20
21
22regularFunction();       
23arrowFunction();         
24
25
26obj.regularMethod();     
27obj.arrowMethod();       
个人笔记记录 2021 ~ 2025