js 关于this

122 阅读2分钟

在 JavaScript 中 this 不是固定不变的,它会随着执行环境的改变而改变。

对象方法中this

当一个函数被当成一个对象的方法调用时,this就是那个对象

var obj = {
    name: 'zhangsan',
    getName: function () {
        console.log(this) // { name: 'zhangsan', getName: [Function: getName] }
        console.log(this.name)  // zhangsan
    }
}
obj.getName()

全局函数中的this

非严格模式下函数中的this指向全局对象

function sayHello() {
    console.log(this)  // 浏览器中指向window
    console.log('hello')
}
sayHello()

严格模式下全局函数中的this

  'use strict'
  function sayHello() {
      console.log(this)
  }
  sayHello()  // undefined

单独使用的this

浏览器中指向window

事件中的this

在事件中,this 表示接收事件的元素。

<button onclick="console.log(this)">dddd</button>

箭头函数中的this

箭头函数中的this绑定定义时的作用域

function Person(name){
    this.name = name;
    this.sayHello = function () {
        setTimeout(() => {
            console.log(this.name)  // person.name
        }, 1000)
    };
    this.sayHello2 = function () {
        setTimeout(function () {
            console.log(this)   // 全局对象
        }, 1000)
    }
  }
var person = new Person("hhh");
person.sayHello()
person.sayHello2()
var obj = {
  name: 'zhang',
  sayHello: function() {
      console.log(this.name)
  },
  sayHello2: () => {
      console.log(this)  // this指向全局变量,因为对象不构成单独的作用域,箭头函数定义时的作用域就是全局作用域。
  }
}
obj.sayHello()
obj.sayHello2()

更改this的指向,call/apply/bind

var person1 = {
    name: 'zhangsan',
    getName: function(place1,place2) {
        console.log(place1)
        console.log(place2)
        console.log(this.name)
    }
}
var person2 = {
    name: 'lisi'
}

person1.getName.call(person2, 'shanghai', 'guangzhou') // lisi // shanghai // guangzhou
person1.getName.apply(person2, ['shanghai', 'guangzhou']) // lisi // shanghai // guangzhou
person1.getName.bind(person2, 'shanghai', 'guangzhou')() // lisi // shanghai // guangzhou

call/apply/bind异同

方法参数返回值
call第一个参数为指定对象,后面多个参数用逗号隔开undefined
apply第一个参数为指定对象,多个参数放在一个数组中undefined
bind第一个参数为指定对象,后面多个参数用逗号隔开this指向新对象的函数

应用1. call/apply/bind 判断变量类型

var arr = [12]
console.log(Object.prototype.toString.call(arr)) // [object Array]

ECMA里是是怎么定义Object.prototype.toString.call的:

Object.prototype.toString( ) When the toString method is called, the following steps are taken:

  1. Get the [[Class]] property of this object.
  2. Compute a string value by concatenating the three strings “[object “, Result (1), and “]”.
  3. Return Result (2)

使用new操作符实例化一个对象时的this

摘自《Javascript 高级程序设计-第三版》,使用new操作符实例化一个对象的步骤

(1) 创建一个新对象;
(2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);
(3) 执行构造函数中的代码(为这个新对象添加属性);
(4) 返回新对象。