轻松理解JS 原型原型链

理解js中原型、原型链这个概念,绝对是帮助咱们更深刻学习js的必要一步,好比,若是js开发者想理解js继承,new关键字原理,甚至封装组件、优化代码,弄明白js中原型、原型链更是前提条件。本篇文章,用最简洁的文字,清楚明白讲解原型链相等关系和原型、原型链存在的意义,看完这篇文章,你会发现,原型、原型链原来如此简单! bash

上面经典的原型链相等图,根据下文的学习,你会轻易掌握。

一:原型、原型链相等关系理解

首先咱们要清楚明白两个概念:函数

  1. js分为函数对象和普通对象,每一个对象都有__proto__属性,可是只有函数对象才有prototype属性
  2. Object、Function都是js内置的函数, 相似的还有咱们经常使用到的Array、RegExp、Date、Boolean、Number、String

这两个概念你们跟我一块儿读三遍并记住,后面会用到学习

那么__proto__和prototype究竟是什么,两个概念理解它们优化

  1. 属性__proto__是一个对象,它有两个属性,constructor和__proto__;
  2. 原型对象prototype有一个默认的constructor属性,用于记录实例是由哪一个构造函数建立;

这两个概念你们跟我一块儿读三遍并记住,后面会用到ui

有如下构造函数Person,他的原型上有所属国属性motherland='china'this

function Person(name, age){ 
    this.name = name;
    this.age = age;
 }
 
 Person.prototype.motherland = 'china'
复制代码

经过new Person()建立的person01实例spa

let person01 = new Person('小明', 18);
复制代码

js之父在设计js原型、原型链的时候听从如下两个准则prototype

1. Person.prototype.constructor == Person // **准则1:原型对象(即Person.prototype)的constructor指向构造函数自己**
2. person01.__proto__ == Person.prototype // **准则2:实例(即person01)的__proto__和原型对象指向同一个地方**
复制代码

这两个准则你们跟我一块儿读三遍并记住,后面会用到设计

记住以上四个概念两个准则,任何原型链相等判断都能判断正确;code

你们能够对照上图,看看本身概念准则是否弄清楚了,必定要对照上图哦

// 从上方 function Foo() 开始分析这一张经典之图
function Foo()
let f1 = new Foo();
let f2 = new Foo();

f1.__proto__ = Foo.prototype; // 准则2
f2.__proto__ = Foo.prototype; // 准则2
Foo.prototype.__proto__ = Object.protitype; // 准则2 (Foo.prototype本质也是普通对象,可适用准则2)
Object.prototype.__proto__ = null; // 原型链到此中止
Foo.prototype.constructor = Foo; // 准则1
Foo.__proto__ = Function.prototype; // 准则2
Function.prototype.__proto__  = Object.protitype; //  准则2 (Function.prototype本质也是普通对象,可适用准则2)
Object.prototype.__proto__ = null; // 原型链到此中止
// **此处注意Foo 和 Function的区别, Foo是 Function的实例**

// 从中间 Function Object()开始分析这一张经典之图
Function Object()
let o1 = new  Object();
let o2 = new  Object();

o1.__proto__ = Object.prototype; // 准则2
o2.__proto__ = Object.prototype; // 准则2
Object.prototype.__proto__ = null; // 原型链到此中止
Object.prototype.constructor = Object; // 准则1
Object.__proto__ = Function.prototype // 准则2 (Object本质也是函数);
// 此处有点绕,Object本质是函数,Function本质是对象
Function.prototype.__proto__ =  Object.prototype; // 准则2 (Function.prototype本质也是普通对象,可适用准则2)
Object.prototype.__proto__ = null; // 原型链到此中止

// 从下方 Function Function()开始分析这一张经典之图
Function Function()
Function.__proto__ = Function.prototype // 准则2
Function.prototype.constructor = Function; // 准则1

复制代码

由此能够得出结论: 除了Object的原型对象(Object.prototype)的__proto__指向null,其余内置函数对象的原型对象(例如:Array.prototype)和自定义构造函数的 __proto__都指向Object.prototype, 由于原型对象自己是普通对象。 即:

Object.prototype.__proto__ = null;
Array.prototype.__proto__ = Object.prototype;
Foo.prototype.__proto__  = Object.prototype;
复制代码

二:原型、原型链的意思何在

理解了这些相等关系以后,咱们思考,原型、原型链的意思何在?原型对象的做用,是用来存放实例中共有的那部份属性、方法,能够大大减小内存消耗。 用咱们文章开始的Person构造函数和person01实例举例说:

console.log(person01)
复制代码

打印person01, 他有本身属性 name = '小明',age = 18; 同时经过原型链关系,他有属性motherland = 'china';

咱们再建立person2实例

let person02 = new Person('小花', 20);
console.log(person02)
复制代码

打印person02, 他有本身属性 name = '小花',age = 20; 同时经过原型链关系,他有属性motherland = 'china'; 看出来了没有,原型对象存放了person0一、person02共有的属性所属国motherland = 'china'. 咱们不用在每一个实例上添加motherland 属性,而是将这一属性存在他们的构造函数原型对象上,对于人类Person这样的构造函数。相同的属性、方法还有不少不少,好比咱们是黑头发,咱们都有吃,睡这样一个方法,当相同的属性、方法越多,原型、原型链的意义越大。 那咱们能够这样操做

Person.prototype.hairColor = 'black';
Person.prototype.eat = function(){
    console.log('We usually eat three meals a day.')
}
console.log(person01)
console.log(person02)
复制代码

此时咱们再打印person0一、person02,咱们惊喜的发现,他们有了属性hairColor和eat方法;实例们动态的得到了Person构造函数以后添加的属性、方法,这是就是原型、原型链的意义所在!能够动态获取,能够节省内存。

另外咱们还要注意:若是person01将头发染成了黄色,那么hairColor会是什么呢?

person01,hairColor = 'yellow';
console.log(person01)
console.log(person02)
复制代码

能够看到,person01的hairColor = 'yellow', 而person02的hairColor = 'black'; 实例对象重写原型上继承的属相、方法,至关于“属性覆盖、属性屏蔽”,这一操做不会改变原型上的属性、方法,天然也不会改变由统一构造函数建立的其余实例,只有修改原型对象上的属性、方法,才能改变其余实例经过原型链得到的属性、方法。

三:结语

若是你们喜欢这边文章,请给我一点鼓励,若是有以为没写讲解清楚的地方,欢迎你们评论里面指正!以前我都是的看别人的文章、博客学习,并从中收获颇多,这是我第一次发表技术类文章,但愿能跟你们交流技术,共同进步。

相关文章
相关标签/搜索