JS 中的 this

JS 中的 this

在 JS 中,this 的指向是调用时决定的,在绝大多数情况下,函数的调用方式决定了 this 的值。

this 对象是是执行上下文中的一个属性,它指向最后一次调用这个方法的对象,在全局函数中,this 等于 window,而当函数被作为某个对象调用时,this 等于那个对象。 在实际开发中,this的指向可以通过四种调用模式来判断。

  1. 函数调用,当一个函数不是一个对象的属性时,直接作为函数来调用时,this 指向全局对象,严格模式下指向 undefined

  2. 方法调用,如果一个函数作为一个对象的方法来调用时,this 指向这个对象。

  3. 构造函数调用,this 指向这个用 new 新创建的对象。

  4. 第四种是 applycallbind 调用模式,这三个方法都可以显示的指定调用函数的 this 指向。apply 接收参数的是数组,call 接受参数列表,bind 方法通过传入一个对象,返回一个 this 绑定了传入对象的新函数。这个函数的 this 指向除了使用 new 时会被改变,其他情况下都不会改变。

new

  1. 首先创建了一个新的空对象

  2. 设置原型,将对象的原型设置为函数的 prototype 对象。

  3. 让函数的 this 指向这个对象,执行构造函数的代码(为这个新对象添加属性)

  4. 判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象。

调用位置

调用位置是函数在代码中被调用的位置,而不是声明的位置 ----- 分析调用栈

function baz() {
    console.log("baz");
    bar();
}
​
function bar() {
    console.log("bar");
    foo();
}
​
function foo() {
    console.log("foo");
}
​
baz();

当调用 baz()时,调用链为baz() -> bar() -> foo()

foo()的调用位置在bar()中;

bar()的调用位置在baz()中;

baz()的调用位置在全局作用域中。

全局上下文

在全局执行上下文中this都指代全局对象。

  • this等价于window对象;

  • var = this. = window

console.log(window === this); // true 
var a = 1;
this.b = 2;
window.c = 3;
console.log(a + b + c); // 6

浏览器中,this等价于window对象,如果声明全局变量,则这些变量都会作为thiswindow的属性。

函数上下文

在函数内部,this的值取决于函数被调用的方式。

1. 直接调用

this指向全局变量。

function foo() {
    return this;
}
console.log(foo() === window); // true

2. call()、apply()

this指向被绑定的对象。

var person = {
    name: "B1ackZz",
    age: 20
};
​
function saySome(job) {
    console.log(`${this.name}:${this.age} ${job}`)
}
​
saySome.call(person, "student"); // B1ackZz:20 student
saySome.apply(person, ["student"]); // B1ackZz:20 student

定义一个saySome函数输出name, age, job,该函数本身没有nameage属性,将这个函数利用call()apply()绑定到person对象上,从而让this指向对象person

如果传入一个原始值(String, Boolean, Number)来作为this的绑定对象,这个原始值会转为其对象形式(new String()),这个过程通常称为“装箱”。

callapplythis的绑定角度上来说是一样的,唯一不同的是它们的第二个参数。

3. bind()

this将永久地被绑定到bind的第一个参数,类似于callapply

var person = {
    name: "B1ackZz",
    age: 20
};
​
function saySome() {
    console.log(`${this.name}: ${this.age}`);
}
​
var f = saySome.bind(person);
console.log(f()); // B1ackZz: 20

4. 箭头函数

所有的箭头函数都没有自己的this,会捕获其所在上下文的this值,作为自己的this值。

function Person(name) {
  this.name = name;
  this.say = () => {
    let name = "bbb";
    return this.name;
  }
}
​
var person = new Person("B1ackZz");
console.log(person.say()); // B1ackZz

箭头函数常常用于回调函数中,如定时器:

function foo() {
  setTimeout(() => {
    console.log(this.a);
  }, 100);
}
​
var obj = {
  a: 2
}
foo.call(obj); // 2

5. 作为对象的一个方法

this指向调用函数的对象。

var name = "aa"
var person = {
  name: "B1ackZz",
  sayName: function() {
    return this.name;
  }
}
console.log(person.sayName()); // B1ackZz
var sayName = person.sayName();
console.log(sayName()); // aa, 因为这里的调用者是window.sayName()

6. 作为构造函数

this指向new创建的对象上。

function Person(name) {
  this.name = name;
  this.age = 20;
  this.say = () => {
    console.log(`${this.name}: ${this.age}`);
  }
}

var person = new Person("B1ackZz");
console.log(person.name); // B1ackZz
person.say(); // B1ackZz: 20

7. 作为一个 DOM 事件处理函数

this指向触发事件的元素,即事件处理程序所绑定到的 DOM 节点。

var el = document.getElementById("id");
el.addEventListener("click", function(e) {
  console.log(this);
  console.log(this === e.target); // true
})

HTML 标签内联事件处理函数

this指向所在的 DOM 元素。

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

总结

如果要判断一个运行中函数的 this 绑定, 就需要找到这个函数的直接调用位置。 找到之后就可以顺序应用下面这四条规则来判断 this 的绑定对象。

  1. new 调用:绑定到新创建的对象,注意:显示return函数或对象,返回值不是新创建的对象,而是显式返回的函数或对象。

  2. call 或者 apply( 或者 bind) 调用:严格模式下,绑定到指定的对象。

  3. 对象上的函数调用:绑定到那个对象。

  4. 普通函数调用: 在严格模式下绑定到 undefined,否则绑定到全局对象。

ES6 中的箭头函数:不会使用上文的四条标准的绑定规则, 而是根据当前的词法作用域来决定。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值