关于JavaScript中this的指向

「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战

前言

在面向对象语言中 this 表示当前对象的一个引用,但在 JavaScript 中的表现略有不同,它会随着执行环境的改变而改变。

this是什么

this是当前执行上下文(globalfunctioneval)的一个属性,在非严格模式下,总是指向一个对象,在严格模式下可以是任意值。

大多数情况下,this会出现在函数中,而在全局作用域中也有this

全局作用域中的this

上面说到在全局作用域中我们也是可以直接打印this的。

浏览器环境:
console.log(this); // window
Node环境:
console.log(this); // {}
console.log(window); // 在node会报错, no defined
复制代码

从这可以看出this在不同的环境上是不一样的。

this的作用

JavaScript中我们在一个对象中想给本身的一个属性赋值往往会使用this.[attr]=xx,这里可以看出this指向的是当前test对象,当没有this时你也可以使用[object name].[attr]的语法来操作属性,但这样子会有个弊端,也就是说当你的对象中里面有很多个方法,而这些方法中很多出现[object name].[attr]语法,那么后续修改对象名称,方法里对于对象名称也需要修改,很不方便。这也即是this的作用。

// 没有使用this
const test = {
  prop: 42,
  func: function() {
    return test.prop;
  },
};

console.log(test.func());
复制代码
// 使用this,this指向当前test对象
const test = {
  prop: 42,
  func: function() {
    return this.prop;
  },
};

console.log(test.func());
复制代码

this的绑定规则

this的绑定规则总有四种分别是默认绑定、隐式绑定、显示绑定、new绑定。下面将对这四种方式展开说明。让你更好的理解this的绑定

默认绑定

  • 独立的函数调用可以理解成函数没有被绑定到某个对象上进行调用
function foo(){
  console.log(this);
}
// 默认绑定,是一个独立函数,没有绑定对象
// 指向window
foo()
复制代码

隐式绑定

  • 它的调用位置是通过某个对象发起的函数调用,例如obj2.bar()
  • object对象会被js引擎绑定到fn函数中this里面
function foo(){
  console.log(this);
}

// 独立函数调用
// foo()

var obj={
  name:'hxh',
  foo:foo
}


obj.foo() // obj对象
复制代码

显示绑定

  • 前提条件
    • 必须在调用的对象内部有一个对函数的引用(比如一个属性)
    • 假使没有这样引用,在进行调用时,会报找不到该函数的错误
    • 正是通过这个引用,间接的将this绑定到这个对象上
  • 如果不希望在对象内部包含这个函数的引用,同时又希望在这个对象上强制调用
    • JavaScript所有的函数都可以使用callapply方法(这个和prototype有关)
    • 这两个函数的第一个参数都要求是一个对象,这个对象是给this准备的
    • 调用这个函数时,会将this绑定到这个传入的对象上
function foo(){
  console.log('函数被调用了');
  console.log(this);
}
var obj={
  name:'obj'
}

foo() // window

foo.call(obj) // obj
foo.apply(obj) // obj
foo.apply('aaa') // aaa
复制代码

new绑定

  • 我们通过一个new关键字调用一个函数时(构造器),这个时候this是在调用这个构造器时创建出来的对象
function Person(name,age) {
  this.name=name
  this.age=age
}
// 自动生成新的obj对象
// 生成的对象赋值到Person中的this
var p1 = new Person('hxh',21);
console.log(p1.name,p1.age);
复制代码

箭头函数

在箭头函数中没有this,如果你在箭头函数中打印thisthis将根据外层作用域来决定this

var foo=()=>{
  console.log(this); // window
}
复制代码

绑定规则优先级

默认绑定 < 隐式绑定 < 显示绑定 < new绑定

显示绑定高于隐式绑定
var obj={
  name:'obj',
  foo:function(){
    console.log(this);
  }
}

// 隐式绑定
obj.foo()
// call apply 绑定高于隐式绑定
obj.foo.call('abc')
复制代码
new绑定优先级高于隐式绑定
var obj={
  name:'obj',
  foo:function (){
    console.log(this)
  }
}

// 打印obj代表隐式绑定优先级高
// 打印foo代表new绑定优先级高
// new优先级高于隐式绑定
var fn=new obj.foo() // foo
复制代码

new绑定和callapply是不允许同时使用的,所以不存在谁的优先级更高。

new绑定优先级高于bind
function foo(){
  console.log(this);
}

var bar=foo.bind('aaa')

var obj=new bar() // foo {}
复制代码

严格模式下的this

在严格模式下,函数中的this默认不是window,而是undefined

'use strict';

console.log(this);// Window

function foo(){
  console.log(this); // undefined
}

foo()
复制代码

猜你喜欢

转载自juejin.im/post/7055549545609953317