this指向
this指向问题一般情况下this的最终指向的是那个调用它的对象
1.全局作用域或者普通函数中this
指向全局对象window(注意定时器里面的this指向window)
<script>
// this指向问题一般情况下this的最终指向的是那个调用它的对象
// 1.全局作用域或者普通函数中this指向全局对象window(注意定时器甲面的this指向window)
console.log(this); //window
</script>
2.函数中的this
**注:**匿名函数中的this也同样指向windows
3.定时器中的this
4.对象或者构造函数中的this
<script>
// 2.调用中谁调用this指向谁
var o = {
sayHi: function() {
console.log(this); // this指向的是o这个对象
}
}
o.sayHi();
// 3.构造函数中this指向构造函数的实例
function fun(name, age) {
this.name = name;
this.age = age;
console.log(this); //指向fun实例对象
}
var fun = new fun();
</script>
- 对象中的this指向它本身
- 构造函数中的this指向它这个构造函数
构造函数中的this因为new的过程使得this指向发生了转移
new的整个过程:
- new会在内存中创建一个新的空对像
- new会让this指向这个新对象
- 执行构造函数中的代码
- return这个新对象
5.绑定事件中的this
谁绑定事件this就指向谁
6.箭头函数this指向 特殊性
箭头函数的this指向它的父作用域,箭头函数声明在全局作用域下其this指向window,若不在全局作用域下,this指向其父作用域
箭头函数的this永远指向其父作用域,箭头函数没有自己的this
普通函数
箭头函数
改变this指向方法
1.call()方法 常用于继承
call(无数个参数);
- 第一个参数:改变this指向
- 第二个参数:实参
- 使用之后会自动执行该函数,不适合用在定时器处理函数或者事件处理函数
2.apply()方法
apply(两个参数)
- 第一个参数:改变this指向
- 第二个参数:数组或者伪数组(里面为实参)
- 特点:使用时候会自动执行函数,不适合用在定时器处理函数或者事件处理函数
3.bind()方法
bind(无数个参数)
- 第一个参数:改变this指向
- 第二个参数之后:实参
- 返回值为一个新的函数
- 使用的时候需要手动调用下返回的新函数(不会自动执行)
- 作用:改变事件处理函数或者定时器处理函数的this指向
三者区别
call、apply与bind区别:前两个可以自动执行,bind不会自动执行,需要手动调用
call、bind与apply区别:前两个都有无数个参数,apply只有两个参数,而且第二个参数为**[数组]**
经典例题🥳
原型和this
function Fn() {
this.x = 100;
this.y = 200;
this.getX = function() {
console.log(this.x);
}
}
Fn.prototype.getX = function() {
console.log(this.x);
};
Fn.prototype.getY = function() {
console.log(this.y);
};
var f1 = new Fn();
var f2 = new Fn();
console.log(f1.getX === f2.getX); //false 两个对象不能全等
console.log(f1.getY === f2.getY); //true 使用的一个构造函数,原型上的方法相同
console.log(f1.__proto__.getY === Fn.prototype.getY); //true 对象的原型方法和构造函数的原型方法相同(指向同一个构造函数)
console.log(f1.__proto__.getX === f2.getX); //false 对象原型的方法和对象的方法不相等
console.log(f1.__proto__.getX === Fn.prototype.getX); //true 对象的原型方法和构造函数的原型方法相同(指向同一个构造函数)
console.log(f1.constructor); //f Fn() 构造函数对象的构造方法是FN()
console.log(Fn.prototype.__proto__.constructor); //空函数 构造函数的原型的构造方法是空函数
f1.getX(); // 100
f1.__proto__.getX(); //undefined 原型上的方法没有给x赋值
f2.getY(); // 200
Fn.prototype.getY(); // undefined 原型上的方法没有给x赋值
解析:
-
第一个false,首先要想到的是 简单数据类型的比较是对值的比较,他们都是存在在栈空间,所以两个值可以相等。而复杂数据类型的比较大不相同,他们在栈空间存放的是地址,当比较两者时,比较的是地址,所以当两个就算是属性相同方法相同的对象比较时,他们的存放地址不同,所以不同。
-
true的原因调用的是同一个原型上的方法,所以相同。
-
true,
f1.__proto__·
指向的是Fn原型,再调用getY方法,这其实就等同于Fn.prototype.getY
直接调用方法 -
false,跟第一个同理,
f1.__proto__.getX
是原型上的方法,其存放地址与实例化对象f2.getX所指向的对象存放地址不相同。并非值的比较。 -
true,
f1.__proto__.getX === Fn.prototype.getX
可以看作Fn.prototype.getX === Fn.prototype.getX
两者相同,都是原型上的方法,地址也相同。 -
实例化对象的constructor指向的是Person,死记。
// 构造函数Person function Person(name, age) { this.age = age; this.name = name; this.say = function() { console.log("我叫", this.name); } } // 验证:实例对象p的constructor属性指向构造函数Person var p = new Person("张三", 18); console.log(p.constructor === Person); //true,验证结果正确
-
ƒ Object() { [native code] }
Fn.prototype指向的是Fn的原型。Fn原型对象的__proto__
指向的是Object对象原型。而Object对象原型的constructor指向的是Object对象,可以参考下图: -
100,f1是一个对象,它调用它自身的getX方法,此时的this只想他自己,所以输出100
-
undefined,
f1.__proto__
指向的是fn原型,首先原型上本身就没有x,y属性值。其次调用的方法中的this指向调用它的对象 -
f2调用原型上的方法,谁调用,this就只想谁。所以输出200
-
跟第9个一样,原型调用自身的方法,this指向自己,没有y值,所以是underfined