0%

关于This

this指向

this指向问题一般情况下this的最终指向的是那个调用它的对象

1.全局作用域或者普通函数中this

指向全局对象window(注意定时器里面的this指向window)

1
2
3
4
5
6
<script>
// this指向问题一般情况下this的最终指向的是那个调用它的对象

// 1.全局作用域或者普通函数中this指向全局对象window(注意定时器甲面的this指向window)
console.log(this); //window
</script>

2.函数中的this

img

注:匿名函数中的this也同样指向windows

3.定时器中的this

img

4.对象或者构造函数中的this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<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的整个过程:

  1. new会在内存中创建一个新的空对像
  2. new会让this指向这个新对象
  3. 执行构造函数中的代码
  4. return这个新对象

5.绑定事件中的this

谁绑定事件this就指向谁

img

6.箭头函数this指向 特殊性

箭头函数的this指向它的父作用域,箭头函数声明在全局作用域下其this指向window,若不在全局作用域下,this指向其父作用域

箭头函数的this永远指向其父作用域,箭头函数没有自己的this

普通函数

img

箭头函数

img

改变this指向方法

1.call()方法 常用于继承

call(无数个参数);

  • 第一个参数:改变this指向
  • 第二个参数:实参
  • 使用之后会自动执行该函数,不适合用在定时器处理函数或者事件处理函数

img

2.apply()方法

apply(两个参数)

  • 第一个参数:改变this指向
  • 第二个参数:数组或者伪数组(里面为实参)
  • 特点:使用时候会自动执行函数,不适合用在定时器处理函数或者事件处理函数

img

3.bind()方法

bind(无数个参数)

  • 第一个参数:改变this指向
  • 第二个参数之后:实参
  • 返回值为一个新的函数
  • 使用的时候需要手动调用下返回的新函数(不会自动执行)
  • 作用:改变事件处理函数或者定时器处理函数的this指向

img

三者区别

call、applybind区别:前两个可以自动执行,bind不会自动执行,需要手动调用

call、bindapply区别:前两个都有无数个参数,apply只有两个参数,而且第二个参数为**[数组]**

经典例题🥳

原型和this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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赋值

解析:

  1. 第一个false,首先要想到的是 简单数据类型的比较是对值的比较,他们都是存在在栈空间,所以两个值可以相等。而复杂数据类型的比较大不相同,他们在栈空间存放的是地址,当比较两者时,比较的是地址,所以当两个就算是属性相同方法相同的对象比较时,他们的存放地址不同,所以不同。

  2. true的原因调用的是同一个原型上的方法,所以相同。

  3. true,f1.__proto__·指向的是Fn原型,再调用getY方法,这其实就等同于Fn.prototype.getY直接调用方法

  4. false,跟第一个同理,f1.__proto__.getX是原型上的方法,其存放地址与实例化对象f2.getX所指向的对象存放地址不相同。并非值的比较。

  5. true,f1.__proto__.getX === Fn.prototype.getX可以看作Fn.prototype.getX === Fn.prototype.getX两者相同,都是原型上的方法,地址也相同。

  6. 实例化对象的constructor指向的是Person,死记。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 构造函数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,验证结果正确
  7. ƒ Object() { [native code] } Fn.prototype指向的是Fn的原型。Fn原型对象的__proto__指向的是Object对象原型。而Object对象原型的constructor指向的是Object对象,可以参考下图:image-20220702174347263New2

  8. 100,f1是一个对象,它调用它自身的getX方法,此时的this只想他自己,所以输出100

  9. undefined,f1.__proto__指向的是fn原型,首先原型上本身就没有x,y属性值。其次调用的方法中的this指向调用它的对象

  10. f2调用原型上的方法,谁调用,this就只想谁。所以输出200

  11. 跟第9个一样,原型调用自身的方法,this指向自己,没有y值,所以是underfined