this关键字
函数执行所在的环境变量,并且是可以改变的。
this是执行上下文中很重要的一个组成部分,
同一个函数调用方式不同,得到的this值也不同,如下:
function showThis(){
console.log(this);
}
var o = {
showThis: showThis
}
showThis(); // global
o.showThis(); // o
普通函数的this是由他调用他所使用的引用来决定的
调用函数时使用的引用,决定了函数执行时刻的 this 值。
场景
1、作为普通函数
const f1 = function() {
console.log(this);
};
f1(); // window
2、作为对象方法被调用
function showThis(){
console.log(this);
}
var o = {
showThis: showThis
}
showThis(); // global
o.showThis(); // o
3、class方法中
class Person {
constructor () {
this.duuty = 'person';
}
say () {
console.log(this); // person实例
}
}
let person = new Person();
person.say();
4、构造函数
let Person = function () {
this.duty = 'person';
}
Person.prototype.say = function () {
console.log(this); // person实例
}
let person = new Person();
person.say();
5、箭头函数
箭头函数,this
的取值,是在函数定义的时候确定的,是在定义时所在的对象,
也就是上级作用域中的this
取值
const showThis = () => {
console.log(this);
}
var o = {
showThis: showThis
}
showThis(); // global
o.showThis(); // global
我们看到,改为箭头函数后,不论用什么引用来调用它,都不影响它的 this 值。
操作this的内置函数
apply和call
作用是在特定的作用域中调用函数,
设置函数体内this
的对象,真正的目的其实是扩容函数的作用域。
function foo(a, b, c) {
console.log(this);
console.log(a, b, c);
}
foo.call({}, 1, 2, 3); // 参数依次传递
foo.apply({}, [1, 2, 3]); // 参数放在数组
这里 call 和 apply 作用是一样的,只是传参方式有区别。
bind
此外,还有 Function.prototype.bind
它可以生成一个绑定过的函数【返回一个副本】,这个函数的 this
值固定了参数:
function foo(a, b, c){
console.log(this);
console.log(a, b, c);
}
foo.bind({}, 1, 2, 3)();
手写bind函数
// 模拟bind的实现
Function.prototype.bind1 = function () {
// 将参数拆解为数组
const args = Array.prototype.slice.call(arguments);
// 获取this,并从数组剔除
const _this = args.shift();
// 原来的fn
const self = this;
// 返回一个函数
return function () {
return self.apply(_this, args);
}
};
function fn () {
console.log(this);
console.log(arguments);
return 'this is a fn';
}
let fn1 = fn.bind1({
name: 'fn',
}, 10, 20);
let res = fn1();
console.log(res);
bind、call和apply的调用效果
let Fruit = function () {
console.log(this);
};
Fruit(); // window
Fruit.prototype = {
color: 'green',
say: function () {
console.log(`my color is ${this.color}`)
}
};
var apple = new Fruit();
apple.say();
let banana = {
color: 'yellow'
};
apple.say.bind(banana)(); // 返回一个副本
apple.say.call(banana); // yellow
apple.say.apply(banana); // yellow