从根源解释JavaScript原型是如何诞生的

151 阅读3分钟

什么是原型?

Javascript里面都是对象,必须有一种机制,将所有对象联系起来。所以,Brendan Eich设计了"继承"。但是他不打算引入"类"(class,ES6 引入了 class,但其只是语法糖的概念)因为一旦有了"类",Javascript就是一种完整的面向对象编程语言了,这好像有点太正式了,而且增加了初学者的入门难度。考虑到这一点,Brendan Eich为所有的构造函数设置了一个prototype属性用来完成对象的继承。

定义

JavaScript 的所有对象中都包含了一个__proto__内部属性,这个属性所对应的就是自身的原型,每个构造函数都有一个原型对象prototype,指向该构造函数创建的实例对象的原型对象。

作用

原型对象是包含特定类型的所有实例共享的属性和方法。原型对象的好处是,可以让所有实例对象共享它所包含的属性和方法

实例对象

最简单的属性封装

	const cat1 = {}; // 创建一个空对象

    cat1.name = "大毛"; // 按照原型对象的属性赋值

    cat1.color = "黄色";

  const cat2 = {};

    cat2.name = "二毛";

    cat2.color = "黑色";

如果多生成几个实例,写起来非常麻烦;

二是实例与原型之间,没有任何办法,可以看出有什么联系。

函数模式

生成实例对象,调用函数,解决代码重复

function Cat(name,color) {

    return {

      name:name,

      color:color

    }

  }

 const cat1 = Cat("大毛","黄色");

 const cat2 = Cat("二毛","黑色");

代码简介了许多,但是cat1cat2之间没有内在的联系,不能反映出它们是同一个原型对象的实例。

构造函数

构造函数,其实就是一个普通函数,但是内部使用了this变量。对构造函数使用new运算符,就能生成实例,并且this变量会绑定在实例对象上。

new运算符

1、创建了一个空对象

2、将空对象的原型__proto__指向构造函数的原型

3、执行构造函数中的代码把属性和方法挂载到空对象中

4、返回一个新对象

 function Person(name){

    this.name = name;
		this.sex="男"
  }
//对这个构造函数使用new,就会生成一个person对象的实例。
  const person1 = new Person('赵子龙');
	const person2 = new Person('张飞');

这时,person1和person2会有一个constructor属性,指向它们的构造函数。

instanceof运算符,可以验证原型对象与实例对象之间的关系。

在上面的例子中,person1和person2的sex属性是独立的,修改其中一个不会影响另一个,每一个实例都有自己属性和方法的副本,这不仅无法做到数据共享,也是极大的资源浪费。

Prototype

构造函数有一个prototype属性,实例对象需要共享的属性和方法,都放在这个对象里面;那些不需要共享的属性和方法,就放在构造函数里面。

function Person(name){
    this.name = name;
  }

    Person.prototype = { sex : '男' };

    const person1= new Person('赵子龙');
    const person2 = new Person('张飞');

参考:阮一峰 Javascript继承机制的设计思想www.ruanyifeng.com/blog/2011/0…