this关键字

函数执行所在的环境变量,并且是可以改变的。

this是执行上下文中很重要的一个组成部分,
同一个函数调用方式不同,得到的this值也不同,如下:

  1. function showThis(){
  2. console.log(this);
  3. }
  4. var o = {
  5. showThis: showThis
  6. }
  7. showThis(); // global
  8. o.showThis(); // o

普通函数的this是由他调用他所使用的引用来决定的

调用函数时使用的引用,决定了函数执行时刻的 this 值。

场景

1、作为普通函数

  1. const f1 = function() {
  2. console.log(this);
  3. };
  4. f1(); // window

2、作为对象方法被调用

  1. function showThis(){
  2. console.log(this);
  3. }
  4. var o = {
  5. showThis: showThis
  6. }
  7. showThis(); // global
  8. o.showThis(); // o

3、class方法中

  1. class Person {
  2. constructor () {
  3. this.duuty = 'person';
  4. }
  5. say () {
  6. console.log(this); // person实例
  7. }
  8. }
  9. let person = new Person();
  10. person.say();

4、构造函数

  1. let Person = function () {
  2. this.duty = 'person';
  3. }
  4. Person.prototype.say = function () {
  5. console.log(this); // person实例
  6. }
  7. let person = new Person();
  8. person.say();


5、箭头函数

箭头函数,this的取值,是在函数定义的时候确定的,是在定义时所在的对象,
也就是上级作用域中的this取值

  1. const showThis = () => {
  2. console.log(this);
  3. }
  4. var o = {
  5. showThis: showThis
  6. }
  7. showThis(); // global
  8. o.showThis(); // global

我们看到,改为箭头函数后,不论用什么引用来调用它,都不影响它的 this 值。

操作this的内置函数

apply和call

作用是在特定的作用域中调用函数,
设置函数体内this的对象,真正的目的其实是扩容函数的作用域。

  1. function foo(a, b, c) {
  2. console.log(this);
  3. console.log(a, b, c);
  4. }
  5. foo.call({}, 1, 2, 3); // 参数依次传递
  6. foo.apply({}, [1, 2, 3]); // 参数放在数组

这里 call 和 apply 作用是一样的,只是传参方式有区别。

bind

此外,还有 Function.prototype.bind它可以生成一个绑定过的函数【返回一个副本】,这个函数的 this 值固定了参数:

  1. function foo(a, b, c){
  2. console.log(this);
  3. console.log(a, b, c);
  4. }
  5. foo.bind({}, 1, 2, 3)();

手写bind函数

  1. // 模拟bind的实现
  2. Function.prototype.bind1 = function () {
  3. // 将参数拆解为数组
  4. const args = Array.prototype.slice.call(arguments);
  5. // 获取this,并从数组剔除
  6. const _this = args.shift();
  7. // 原来的fn
  8. const self = this;
  9. // 返回一个函数
  10. return function () {
  11. return self.apply(_this, args);
  12. }
  13. };
  14. function fn () {
  15. console.log(this);
  16. console.log(arguments);
  17. return 'this is a fn';
  18. }
  19. let fn1 = fn.bind1({
  20. name: 'fn',
  21. }, 10, 20);
  22. let res = fn1();
  23. console.log(res);

bind、call和apply的调用效果

  1. let Fruit = function () {
  2. console.log(this);
  3. };
  4. Fruit(); // window
  5. Fruit.prototype = {
  6. color: 'green',
  7. say: function () {
  8. console.log(`my color is ${this.color}`)
  9. }
  10. };
  11. var apple = new Fruit();
  12. apple.say();
  13. let banana = {
  14. color: 'yellow'
  15. };
  16. apple.say.bind(banana)(); // 返回一个副本
  17. apple.say.call(banana); // yellow
  18. apple.say.apply(banana); // yellow