原型和原型链的抽筋拔骨

一丶前言

最近的学习中老是时不时的遇到原型相关问题,不胜困扰,因而决定学学哪吒闹海,对“东海三太子”进行抽筋拔骨。但愿你在看完本文以后感觉是这样的:javascript


二丶我有故事,君有酒否?

世人皆爱听故事,在听各类之乎者也以前不如容小生给你们讲个故事。在好久好久之前,js是孤独的,他没爹没妈,没妻没子。js转念一想,总不能叫孤儿吧,因而美其名曰:“null先生”。有一天,null先生捡到了一只鸡和一枚鸡蛋,非常高兴,给鸡蛋取名为Object因为他先看到鸡后看到蛋,因而他认为鸡是属于他的,这只鸡呢又是由鸡蛋孵化的,为了方便理清这层关系,他使用prototype__proto__来进行区分,并规定:html

Object.prototype = 鸡;
鸡.__proto__ = null;复制代码

以图示之:java


null先生并不安分,他认为鸡给他带来了不少乐趣,他得回报啊,因而他动手为鸡造了一个鸡窝,并规定,这个鸡窝是给鸡的,因而:bash

鸡窝.__proto__ = 鸡;复制代码

以图示之:函数


自从有了这个鸡窝,null先生今后和鸡过上了没羞没臊的生活。。。。。。额,不是,是有了这个鸡窝,鸡竟然生小鸡了,但凡这只鸡走进鸡窝,没多久就能从里面产出小鸡来,amazing!null先生想这确定是这个鸡窝的功劳,兴奋之余,他发现虽然都是鸡,但颜色,大小等都各有差别,你们都是鸡,你装什么高贵。null先生虽然这么想,但为了区分仍是根据它们的特性进行命名:StringNumberBooleanArray。。。。。。这时null先生再望向那枚起始的鸡蛋,一拍大腿,鸡生蛋,蛋生鸡,这枚鸡蛋(Object)也能够归属到鸡窝才是!学习

Object.__proto__ = 鸡窝;复制代码

null先生觉得日子总该平静了吧,但鸡就是鸡,一天不搞事浑身难受,有一种浑身彩色的小鸡咱们简称为彩鸡,它干了什么呢?它竟然能够本身造窝,不只如此,它造出来的鸡窝和null先生造的鸡窝功能是同样的,也能产小鸡,null先生不由叹服:好你个彩鸡,竟然有如此之本领,这般放荡,要克制本身的本性才好。因而给这种彩鸡取名为“放克性”,彩鸡不服,兄弟姐妹们都是英文名凭啥我是中文名,便自我更名Function。有了这层关系,咱们大胆得出结论:spa

String.__proto__ = 鸡窝;
Number.__proto__ = 鸡窝;
...
Function.__proto__ = 鸡窝;
Function.prototype = 鸡窝;复制代码

以图示之:.net


啊~null先生大叹一声,这日子何时是个头啊!其实,这才刚刚开始。。。。。。prototype

好了,故事讲完了,根据以上信息咱们得出如下结论:指针

Object.__proto__ === Function.prototype;
Function.prototype.__proto__ === Object.prototype;
Object.prototype.__proto__ === null;复制代码

三丶给对象划分三六九等

咱们常说“万物皆对象”是由于javascript任何值或变量都是对象,可是对象也能够划分为三六九等。

公爵——Object

Javascript中全部的对象都是Object的实例,并继承Object.prototype的属性和方法,全部的对象都是间接或直接的经过Object衍生的。这个大哥Object当之无愧。

侯爵——Function

当咱们定义一个对象时,能够用var obj = new Object(),咱们都知道new是用来实例化一个对象的方法,可是咱们都知道javascript中不存在真正的类的概念,因此只能用函数来模拟,那么既然能够有上面的作法也就印证了Object也是特殊的函数。  咱们回到刚才的故事,Object是蛋,Function是鸡,那你以为是鸡生蛋仍是蛋生鸡呢?成年人没空思考,小孩又想不出答案。。。。。。

伯爵——String,Number,Boolean,Array...

子爵——其余

四丶原型和原型链

讲了这么多,那么到底何为原型,何为原型链呢???

4.1 原型

每一个函数都有prototype(原型)属性,这个属性是一个指针,指向一个对象,这个对象的用途是包含特定类型的全部实例共享的属性和方法,咱们称这种对象为原型对象,即这个原型对象是用来给实例共享属性和方法的。也就是说Function.prototype = 原型对象,如今再想一想那群鸡和鸡窝是否是恍然大悟,鸡窝原来就是原型对象!

既然函数这么特殊,那么咱们在此将对象分为 函数对象普通对象,函数对象是经过使用function定义的对象,而普通对象是经过使用 new操做符生成的对象。函数对象有一个 prototype属性,普通对象就没有这个 prototype属性,存在 __proto__。咱们来看几个例子:

var obj = new Object();
console.log(obj.__proto__);//Object原型对象
console.log(obj.prototype);//undefined
console.log(Object.prototype);//Object原型对象
console.log(obj.__proto__ === Object.prototype)//true


var Fn = function(){};
var fn = new Fn();
console.log(Fn.prototype);//Object {constructor: function}
console.log(fn.__proto__);//Object {constructor: function}
console.log(fn.__proto__ === Fn.prototype);//true复制代码

实际上每一个实例内部都有一个指向原型对象的指针。所以:若var a = new A();则a.__proto__=A.prototype

4.2 原型链

谈到原型链就不得不谈到__proto__,上面咱们有谈到,每一个对象都会在其内部初始化一个属性,就是__proto__当咱们访问一个对象的属性时,若是这个对象内部不存在这个属性,那么它就会去__proto__里找这个属性,这个__proto__又会有本身的__proto__,因而就这样 一直找下去,也就是咱们平时所说的原型链的概念。举一个构造函数中常常遇到的实例:

var Fn = function(){};
Fn.prototype.sayLove = function(){
    console.log("I love XX");
}
var fn = new Fn();
fn.sayLove();//I love XX;复制代码

当咱们调用fn.sayLove()时会输出"I love XX",那么fn是如何找到这个方法的呢?首先fn做为实例对象,自己并不存在sayLove()方法,从而它就会去找fn.__proto__,由于fn是Fn的实例,所以fn.__proto__ = Fn.prototype,而咱们上边定义了Fn.prototype.sayLove = function(){},所以fn.sayLove()天然也就输出了"I love XX"。

初来贵宝地,有钱的捧个赞场,没钱的点个关注再走。

五丶参考资料

深刻理解JavaScript原型链
Object.prototype原型和原型链
JS原型和原型链是什么?
JavaScript 世界万物诞生记
相关文章
相关标签/搜索