关于面试中的this问题究竟怎么回答?

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36407748/article/details/86595405
/**
 * 函数的this理解
 * 经常看到的一句话:就是js代码在执行时,谁调用这个函数或方法,this关键字就指向谁
 * 为什么说是js代码在执行时?
 * 因为js设计的就是代码在浏览器中运行时才为this分配上下文,这是它的坑
 * 也就是说this的指向只有在代码运行时才确定的,而不是定义时确定的 
 * 谁调用这个函数或方法,this关键字就指向谁,才决定了this的作用域!
 * 所以js中的this指向谁,是由下边的这几种调用模式决定的
 * js中的调用模式
 *  普通函数调用
    作为方法来调用
    作为构造函数来调用
    使用apply/call方法来调用
    Function.prototype.bind方法
	es6箭头函数
 */
// 普通函数调用  this指向 window

console.log('**普通函数调用========this指向 window');

function sum() {
  console.log(this); // window
}
sum();

console.log('**作为方法来调用======this 指向当前对象');

// 作为方法来调用    this 指向当前对象
var peroson = {
  name: 'lisi',
  age: 15,
  say() {
    console.log(this); //=> {name: "lisi", age: 15, say: ƒ}
    return this.name + this.age;
  }
};
peroson.say();

console.log('**作为构造函数来调用======this 指向当前实例化的对象');

function Animal(name, age) {
  this.name = name;
  this.age = age;
  this.run = function() {
    console.log(this); // => Animal {name: "哈士奇", age: 5, run: ƒ}
    return this.name + ' ' + this.age;
  };
}
let animal = new Animal('哈士奇', 5);

console.log(animal.run()); //=>  哈士奇 5

console.log(
  '**使用apply/call方法来调用======this指向取决于两个方法的第一个参数'
);

/**
 * 在apply(),call() 方法中,接收两个参数,第一个参数是this指向,
 * 第二个参数在apply()中是数组,在call()中是普通的形参,比如字符串等
 */

// 使用 构造函数定义一个长方形
function Rectangle(width, height) {
  this.width = width;
  this.height = height;
  this.getRectangle = function() {
    console.log(this);
    return `长度是:${width},高度是:${height}`;
  };
}
// 实例化一个长方形
let a = new Rectangle(10, 20);
/**
 * 当调用a.getRectangle()时,Rectangle()函数中的this 指向的时它的实例
 */
a.getRectangle();

let model = {
  width: 35,
  height: 50
};
/**
 * 当model对象在调用js的call()||apply()方法后,Rectangle()函数中的this就指向了model对象
 */

a.getRectangle.apply(model);

/**
 * apply(),call()方法使用
 */
// 最简单的举例 求最大值
let arr = [1, 5, 25, 68, 59];

/**
 * 我们知道Math对象有个max()方法,由于参数是个数组,使用apply()方法 ,
 * 当第一个参数是null||undefind时,this指向window
 */
console.log(Math.max.apply(null, arr));
console.log(Math.max.apply(undefined, arr));

console.log('**Function.prototype.bind方法===== this指向当前的这个对象函数');

// 模拟异步
// 创建一个水果的模型,
/**
 *
 * @param {*} name  水果名称
 * @param {*} color 水果颜色
 * @returns 水果的颜色
 */
function Fruit(name, color) {
  this.name = name;
  this.color = color;
  this.change = function() {
    console.log(this); // 这个this 指向了 Fruit {name: "苹果", color: "黑色", change: ƒ}的实例
    //   1秒后打印水果的颜色
    setTimeout(function() {
      console.log(this); // 这个this 指向了 window
      console.log(this.name + '的颜色是 ' + this.color);
    }, 1000);
  };
}

let apple = new Fruit('苹果', '黑色');
apple.change(); // => 的颜色是 undefined

/**
 * 我们知道,在浏览器BOM中的方法,this统统是指向window的,所以在构造函数中Fruit()中,
 * change()方法里的定时器里的this是指向window的,并不是当前的构造函数的实例apple的
 *
 * 解决:
 * 1.用bind()将this指向绑定到当前实例化的对象
 *
 * 2.用es6中的箭头函数
 *
 */

// 使用bind();   //  可以看到 输出了 (苹果的颜色是黑色)
function Fruit(name, color) {
  this.name = name;
  this.color = color;
  this.change = function() {
    console.log(this); // 这个this 指向了 Fruit {name: "苹果", color: "黑色", change: ƒ}的实例
    //   1秒后打印水果的颜色
    setTimeout(
      function() {
        console.log(this); // 	此时this 指向了当前实例
        console.log(this.name + '的颜色是' + this.color);
      }.bind(this),
      1000
    );
  };
}

console.log(
  '**es6的箭头函数===== es6里面this指向固定化,始终指向父级的运行上下文环境,因为箭头函数没有this,因此它自身不能进行new实例化,同时也不能使用call, apply, bind等方法来改变this的指向'
);

function Fruit(name, color) {
  this.name = name;
  this.color = color;
  this.change = function() {
    console.log(this); // 这个this 指向了 Fruit {name: "苹果", color: "黑色", change: ƒ}的实例
    //   1秒后打印水果的颜色
    setTimeout(() => {
      console.log(this); 	// 此时this也 指向了当前实例
      console.log(this.name + '的颜色是' + this.color);
    }, 1000);
  };
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_36407748/article/details/86595405
今日推荐