this指针
什么是this指针
this指执行上下文,通常指向一个对象。在严格模式下有一点不同,体现在函数中调用this指针。
/*非严格模式*/
function demo(){
alert(this);
}
demo();//windows
/*严格模式*/
function demo() {
"use strict";
alert(this);
}
demo();//undefined
在全局中,this总是指向windows对象。
this;
//Window {window: Window, self: Window, document: document, name: '', location: Location, …}
在函数中,this的指向有几种情况:
-
直接调用函数,this指向全局windows
-
使用new关键字实例化一个构造函数,this指向新创建的实例化对象
- 调用对象内的函数,this指向这个对象
4. 在HTML元素中插入行内脚本,脚本中的this指针默认指向当前HTML元素。
<h1 onclick="alert(this.innerHTML)">Hello!</h1>
这里的this指针默认指向h1元素
- 箭头函数中的this指针继承父级作用域的this指针
var a =0;
function foo() {
var a =50;
let show = ()=> {
var a = 55;
console.log(this.a);
}
show();
}
let obj={
a:666,
}
foo();//输出:0
foo.call(obj);// 输出666
箭头函数的this继承父作用域foo(),而这个作用域是定义在全局windows下的,所以foo作用域内的this指针指向全局windows,故箭头函数内的指针也指向全局windows。
如果此时用call方法改变foo函数的this指针指向。那么箭头函数内的this指针指向也会发生变化,由此可以证明:箭头函数内的this指针指向继承父作用域的this指针指向。
bind()、call()、apply()方法
这三个方法都是用于改变this的指向。
三个方法的语法都是:bind(some_object)
第一个参数是你要让this重新指向的对象,其他是传入的值,多余的值会被忽视
这里用一个借充电宝的例子讲解这三个方法。————例子来自B站CodingStartup起码课
先定义两个人,一个是Steven,一个是Backy。
Steven的手机电量(phoneBattery)是70,而且他有充电宝(charge函数),函数内level表示冲入的电量。
Backy的手机电量是30,而且她没有充电宝。
const steven = {
name: 'Steven',
phoneBattery: 70,
charge: function(level) { //充电宝
this.phoneBattery += level;
}
/*charge: function(...level) { //可以使用剩余参数
this.phoneBattery = level.reduce((pre, acc) => { return level = acc + pre });*/
//调用的时候就可以不限制传值个数
// steven.charge.call(Backy, 30, 70, 440);
//借充电宝充电后,Backy的手机电量:540
}
}
const Backy = {
name: 'Backy',
phoneBattery: 30,
//没有充电宝
}
bind
Backy的手机没电了,她就需要找Steven借充电宝来充电。
console.log('借用Steven的充电宝充电前,Backy的手机电量:' + Backy.phoneBattery);
steven.charge.bind(Backy, 70);
console.log('借充电宝充电后,Backy的手机电量:' + Backy.phoneBattery);//输出:借充电宝充电后,Backy的手机电量:30
最后Backy的电量依然是30,这并不是因为bind方法没有起作用,bind方法只负责重新调整this的指向,但是不负责执行。
这是因为,bind方法返回的是一个普通函数,需要调用才会执行。要让bind方法执行的话只需要将上面代码块的第三条语句改为
steven.charge.bind(Backy, 70)();
console.log('借充电宝充电后,Backy的手机电量:' + Backy.phoneBattery);//输出:借充电宝充电后,Backy的手机电量:100
call
call()和bind()唯一的区别就是call会立即执行。
所以 call();=bind()();
console.log('借用Steven的充电宝充电前,Backy的手机电量:' + Backy.phoneBattery);
steven.charge.call(Backy, 70);
console.log('借充电宝充电后,Backy的手机电量:' + Backy.phoneBattery);//输出:借充电宝充电后,Backy的手机电量:100
apply()
apply()调用的时候也会立即执行,它与前面两个方法不同之处在于,apply方法接受的参数是一个数组。
const steven = {
name: 'Steven',
phoneBattery: 70,
charge: function(...level) { //充电宝
this.phoneBattery = level.reduce((pre, acc) => pre+acc);
}
}
const Backy = {
name: 'Backy',
phoneBattery: 30,
//没有充电宝
}
console.log('借用Steven的充电宝充电前,Backy的手机电量:' + Backy.phoneBattery);
steven.charge.apply(Backy, [20, 20, 20, 20, 20]); //apply传入的是一个数组
console.log('借充电宝充电后,Backy的手机电量:' + Backy.phoneBattery);
//借充电宝充电后,Backy的手机电量:100