/**
* 函数的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);
};
}
转载自:https://blog.csdn.net/qq_36407748/article/details/86595405