Js原型及原型链

1.原型的概念离不开构造函数,首先需要了解构造函数。
1.1. 构造函数分为实例成员和静态成员
实例成员:在构造函数内部,通过this添加的成员,其只能通过实例化的对象来访问。
静态成员:在构造函数本身上添加的成员,只能通过构造函数访问。

function emp(name,age){
      //实例成员
      this.name = name;
      this.age = age;
}
//静态成员
emp.sex = '男';

let eOne = new emp('老董',30);
console.log(eOne);      // emp{name: "老董", age: 30}
console.log(eOne.sex);  // undefined     实例无法访问sex属性

console.log(emp.name); //emp   通过构造函数无法直接访问实例成员
console.log(emp.sex);  //男    通过构造函数可直接访问静态成员

1.2 通过构造函数创建对象(该过程也叫实例化)

function Student(name) {
     this.name = name;
 }
 let stu1 = new Student('小王');
 console.log(stu1); //Student{name: "小王"}

此时,Student就是一个新对象

1.2.1 在new一个新对象的过程中,发生了如下步骤:
①创建了一个空的stu1{}对象
②为stu1准备原型连接接stu1.proto = Student.prototype
③重新绑定this,使构造函数的this指向新对象Student.call(this)
④为新对象赋值,stu1.name
⑤返回this return this,此时的新对象就拥有了构造函数的方法和属性了

1.2.2 区分实例的方法是否共享
结论:在构造函数直接定义为不共享的,通过原型链添加的方法为共享方法。
构造函数直接定义(非共享):

function Student() {
        this.sing = function () {
            console.log('我爱唱歌');
        }
    }
    let stu1 = new Student();
    let stu2 = new Student();
    stu1.sing();//我爱唱歌
    stu2.sing();//我爱唱歌
    console.log(stu1.sing === stu2.sing);//false

很明显,stu1 和 stu2 指向的不是一个地方。所以 在构造函数上通过this来添加方法的方式来生成实例,每次生成实例,都是新开辟一个内存空间存方法。这样会导致内存的极大浪费,从而影响性能。

通过原型添加方法(共享):

function Student(name) {
        this.name = name;
    }
    Student.prototype.sing = function () {
        console.log('我爱唱歌', this.name);
    };
    let stu1 = new Student('小汪');
    let stu2 = new Student('小徐');
    stu1.sing();//我爱唱歌 小汪
    stu2.sing();//我爱唱歌 小徐
    console.log(stu1.sing === stu2.sing);//true

2.原型
2.1 经过以上例子,Student.prototype 其实就是原型,本质上其为对象,所以叫原型对象。
2.2 原型的作用就是用来共享方法(通过Student.prototype.method共享方法,而不会开辟空间储存方法)
2.3 原型中的this指向的就是实例

3.原型链
3.1 原型 与 原型 层层相链接的过程即为原型链
3.2 原型链的应用:对象可以使用构造函数prototype原型对象的属性和方法,就是因为对象有__proto__原型的存在(每个对象都有__proto__原型的存在)

function Student(name,age) {
    this.name = name;
    this.age = age;
}
Student.prototype.eat = function(){
    console.log('吃饭',this.name);
};
let obj = new Student('自gay',12);
console.log(obj.__proto__ === Student.prototype);//true

3.3 原型查找方式
function Student(name) {
this.name = name;

    (1)首先看obj对象身上是否有eat方法,如果有,则执行对象身上的方法
    this.eat= function () {
        console.log(this.name + '1');
    }
}

(2)如果没有eat方法,就去构造函数原型对象prototype身上去查找eat这个方法。
Student.prototype.eat= function () {
    console.log(this.name + '2');
};

(3)如果再没有eat方法,就去Object原型对象prototype身上去查找eat这个方法。
Object.prototype.eat= function () {
    console.log(this.name + '3');
};
(4)如果再没有,则会报错。
let obj = new Student('小张');
obj.eat();

3.4 原型链图

原文地址:https://www.cnblogs.com/bemad/p/13070983.html