JS-原型链和This指向总结

原型链

我们想要了解原型链之前需要先知道自定义构造函数原型对象 以及 对象的实例

自定义构造函数

  • 假如我们像现在需要创建一个对象,我们可能会用 字面量方法构造函数方法来完成,那现在呢?我们可以在构造函数方法的基础上用自定义函数的方法来完成

格式:

function 函数名(参数1,参数2.........){
    //为对象添加属性和方法
    this.属性名 = 属性值;
    //构造函数会自动创建对象,并返回,不需要我们手动创建和返回。
}
//调用
new 函数名();
复制代码

例子

function Animal(name,age){
    this.name = name;
    this.age = age
}
var obj = new Animal(); //创建一个Animal的实例对象,返回给obj;
复制代码

如上创建的这个Animal对象就是自定义构造函数,用new关键字调用Animal后返回给obj就是Animal的一个实例

自定义构造函数的返回值&对比普通函数

返回值

  • 默认返回新创建对象的实例的内存地址(上边例子obj的地址)
  • return引用数据类型,则返回被引用的数据类型的数据
  • return基础数据类型,是无效的操作,依然返回默认值

与普通函数的区别

  • 调用方式不同:自定义构造函数需要new关键字
  • 返回值的不同:普通函数的返回值就是函数体中return后面的内容

原型对象&原型链

原型对象是什么?我们创建的函数中都有一个prototype属性,该属性指向一个对象。这个对象就叫做原型对象

原型对象的特点: 原型对象上所有的属性和方法,都会被自定义构造函数创建出来的实例对象所拥有

对象的 __proto__ 每一个对象上都有一个__proto__属性。 该属性指向该对象的原型对象

                      说了这么多是不是有点迷,上图看下“原型链”!!!
复制代码

原型对象与实例关系.png 看完了这个图解后再来看个例子,看看是不是理解了呢✈

function Animal(name) {
      this.name = name;
    }
    // 通过自定义构造函数的 Animal 的 prototype 属性找到 Animal 的原型对象
    Animal.prototype.eat = function () {
      console.log("吃饭");
    }
    // Animal的实例1和实例2
    let p1 = new Animal("猴子", 4);
    let p2 = new Animal("老虎", 6);
     console.log(Animal.__proto__);// Animal它自己,就是说Animal的原型就是它自己(注意区分Animal的原型对象)
    console.log(p1);
    console.log(p2);
    console.log(p1.eat === p2.eat); // true 说明猴子和老虎的吃指向的是一个地方,即Animal的的prototype
复制代码

原型链概念: 当我们访问一个对象的属性时,会先在对象本身查找,有没有这个属性。如果没有,则去该对象上的原型对象上查找。如果还没有,继续去原型对象上的原型对象上查找,直到Object的原型对象为止

This指向

注意

  • 在每一个函数中,都有一个内置的变量:this
  • 大多数情况下,this存储的是当前函数的调用者
  • this指向在定义时是不确定的,在不同的情况下,this指向是不一定相同的

This指向的几种情况

1. 全局函数中,this指向window

function fn(){
    console.log(this)//指向window
}
var fn = function(){
    console.log(this)//指向window
}
fn();
复制代码

2. 对象的方法中,this指向该对象

var obj = {
    name:"洋葱"run:function(){
        console.log(this)
    }
}
obj.run() // this指向obj
--------------------------------------------------------------------------
a.b.c.d() // d中的this指向c(注意)  
复制代码

3. 事件绑定中this指向事件源

btn.onclick = function(){
    //this 指向的就是btn元素节点。
--------------------------------------------------------------------------    
    fn();//this指向 window(注意)
}
复制代码

4. 自定义构造函数中,this指向新的实例化对象

function Animal(name, age) {
    this.name = name;
    this.age = age;
}
var p = new Animal(1,2) // this指向新创建的实例对象
复制代码

5. 定时器函数中,this指向window

setTimeout(function(){
    //this 指向window
},1000)
复制代码

有时候我们并不希望this指向按照默认的规则来,那么我们就需要修改this指向

修改this指向的三个方法

1. call

格式:函数.call(参数one,参数2,参数3,.........)
参数:
    1.第一个参数,函数内部this的指向 (第一个参数是谁,this就指向谁)
    2.从第二个参数开始,为函数依次传递参数。
复制代码

2. apply

格式: 函数.apply(参数one,[数组/伪数组]);
参数:
    1.第一个参数:函数内部的this指向(第一个参数是谁,this就指向谁。)
    2.第二个参数:数组/伪数组。数组中的每一个元素都是函数的参数。
复制代码

以上两种方法修改后都会立即执行函数,所以某些情况是不适用的

3. bind

格式:函数.bind(参数one,参数2,参数3........)
参数:
    1.第一个参数:函数内部的this指向(第一个参数是谁,this就指向谁。)
    2.从第二个参数开始,为函数依次传递参数。  
返回值:新的函数。新函数与旧函数的功能一模一样,只是内部的this指向发生了变化。
##########【重点】不会立即执行函数,可用于事件处理函数和定时器函数.############
复制代码

总结

原型链和自定义构造函数是原型继承和构造函数法继承的基础,下一篇我们来说一下继承,以及Es6的继承方法

猜你喜欢

转载自juejin.im/post/7033187356349825055