this关键字
函数执行所在的环境变量,并且是可以改变的。
this是执行上下文中很重要的一个组成部分,
同一个函数调用方式不同,得到的this值也不同,如下:
function showThis(){console.log(this);}var o = {showThis: showThis}showThis(); // globalo.showThis(); // o
普通函数的this是由他调用他所使用的引用来决定的
调用函数时使用的引用,决定了函数执行时刻的 this 值。
场景
1、作为普通函数
const f1 = function() {console.log(this);};f1(); // window
2、作为对象方法被调用
function showThis(){console.log(this);}var o = {showThis: showThis}showThis(); // globalo.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(); // globalo.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();// 原来的fnconst 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(); // windowFruit.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); // yellowapple.say.apply(banana); // yellow
