Web前端之路让前端飞JavaScript 进阶营

JavaScript的原型及原型链

2017-08-04  本文已影响112人  BarryLiu1995

引言:javascript王国的一次旅行,一个没有类的世界怎么玩转面向对象? 一文中我们提到了在没有类概念的 JavaScript 语言中是通过原型来实现面向对象的继承特性。只要运用得好,这种基于原型的 JavaScript 继承模型比传统的类继承还要强大。所以我们还需详细学习一下原型的知识


JavaScript 的对象

JavaScript 是基于对象的面向对象语言。因此在这里的“对象”既可以是普通对象(Object),也可以是函数对象(Function)。JS 抛弃了 Java 的类概念,而 Java 的继承恰恰是通过类来实现的。那么 JS 没有类的概念,就使用了“原型”的概念来实现继承。

字面量原型及原型链

JS 可通过字面量构造对象。为了实现继承,对象里面有个_proto_属性可以指向该对象的父对象。这个父对象就是所谓的“原型”。

var animal = {
  name: '动物',
  eat: function(){
    console.log(this.name + " is eating");
  }
};

animal.eat();     // animal is eating

var dog = {
  name: '狗',
  _proto_: animal
};

var cat = {
  name: '猫',
  _proto_: animal
};

dog.eat();        // 狗 is eating
cat.eat();        // 猫 is eating

由上面代码我们可以看出:dog 和 cat 对象的原型都是 animal。但是 dog 和 cat 对象都没有定义 eat()方法,那怎么可以调用呢?其实当eat方法被调用的时候,先在自己的方法列表中寻找, 如果找不到,就去找原型中的方法, 如果原型中找不到, 就去原型的原型中去寻找...... 最后找到Object那里, 如果还找不到, 那就是未定义了。这几个对象通过_proto_属性建立一个原型链!

构造函数原型链

由上面的代码和示意图可看出这个所谓的构造函数 Student 其实就是一个幌子啊, 每次去new Student的时候,确实会创建一个对象出来( andy 或者 lisa ) , 并且把这个对象的原型指针(_proto_)指向 Student.prototype 这个对象,这样一来就能找到sayHello()方法了。我们应该还知道上面的构造函数Student()对象(JS 中函数也是对象)会创建一个 prototype 对象(Student.prototype),而 new 出来的实例对象例如 andy 和 lisa 是没有这个 prototype 对象,但是他会有个 proto 属性(_proto_)指向这个构造函数对象的 prototype 对象,从而构成原型链。实例对象其实是通过原型对象与构造函数取得联系的。为了让 Java、C#、C++ 程序员降低学习成本,JavaScript 提供了语法糖:

class Student {
  constructor(name){
    this.name = name;
  }
  sayHello(){
    console.log("Hi, I'm "+this.name);
  }
}

var andy = new Student("andy");   
andy.sayHello();                     //Hi, I'm andy

Object.create()

var a = Object.create(null);
console.log(a);                 //{}
a.name = 'Zhiyu';
var b = Object.create(a);
console.log(b);                 //{}
console.log(b.name);            //Zhiyu

上面我们可以看出该方法是创建一个空对象,空对象的原型是create()参数。此时创建的空对象会有个(_proto_)属性指向方法参数,这样也可以构成一个原型链。

总结

  1. JS 在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做 _ proto_ 的内置属性,用于指向创建它的函数对象的原型对象 prototype
  2. 原型和原型链是 JS 实现继承的一种模型
  3. 原型链是靠 _proto _ 形成的,而不是 prototype
  4. 所有的原型对象都有 constructor 属性,该属性对应创建所有指向该原型的实例构造函数
  5. 函数对象和原型对象通过 prototype 和 constructor 属性进行相互关联

参考

最后是广告时间,我的原创博文将同步更新在三大平台上,欢迎大家点击阅读!谢谢

刘志宇的新天地

简书

稀土掘金

上一篇 下一篇

猜你喜欢

热点阅读