最近的学习中老是时不时的遇到原型相关问题,不胜困扰,因而决定学学哪吒闹海,对“东海三太子”进行抽筋拔骨。但愿你在看完本文以后感觉是这样的:javascript
世人皆爱听故事,在听各类之乎者也以前不如容小生给你们讲个故事。在好久好久之前,js是孤独的,他没爹没妈,没妻没子。js转念一想,总不能叫孤儿吧,因而美其名曰:“null先生”。有一天,null先生捡到了一只鸡和一枚鸡蛋,非常高兴,给鸡蛋取名为Object
,因为他先看到鸡后看到蛋,因而他认为鸡是属于他的,这只鸡呢又是由鸡蛋孵化的,为了方便理清这层关系,他使用prototype
和__proto__
来进行区分,并规定:html
Object.prototype = 鸡;
鸡.__proto__ = null;复制代码
以图示之:java
null先生并不安分,他认为鸡给他带来了不少乐趣,他得回报啊,因而他动手为鸡造了一个鸡窝,并规定,这个鸡窝是给鸡的,因而:bash
鸡窝.__proto__ = 鸡;复制代码
以图示之:函数
自从有了这个鸡窝,null先生今后和鸡过上了没羞没臊的生活。。。。。。额,不是,是有了这个鸡窝,鸡竟然生小鸡了,但凡这只鸡走进鸡窝,没多久就能从里面产出小鸡来,amazing!null先生想这确定是这个鸡窝的功劳,兴奋之余,他发现虽然都是鸡,但颜色,大小等都各有差别,你们都是鸡,你装什么高贵。null先生虽然这么想,但为了区分仍是根据它们的特性进行命名:String
、Number
、Boolean
、Array
。。。。。。这时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任何值或变量都是对象,可是对象也能够划分为三六九等。
Javascript中全部的对象都是Object
的实例,并继承Object.prototype
的属性和方法,全部的对象都是间接或直接的经过Object
衍生的。这个大哥Object
当之无愧。
当咱们定义一个对象时,能够用var obj = new Object()
,咱们都知道new
是用来实例化一个对象的方法,可是咱们都知道javascript中不存在真正的类的概念,因此只能用函数来模拟,那么既然能够有上面的作法也就印证了Object
也是特殊的函数。 咱们回到刚才的故事,Object
是蛋,Function
是鸡,那你以为是鸡生蛋仍是蛋生鸡呢?成年人没空思考,小孩又想不出答案。。。。。。
讲了这么多,那么到底何为原型,何为原型链呢???
每一个函数都有prototype(原型)属性,这个属性是一个指针,指向一个对象,这个对象的用途是包含特定类型的全部实例共享的属性和方法,咱们称这种对象为原型对象,即这个原型对象是用来给实例共享属性和方法的。也就是说Function.prototype = 原型对象
,如今再想一想那群鸡和鸡窝是否是恍然大悟,鸡窝原来就是原型对象!
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
。
谈到原型链就不得不谈到__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 世界万物诞生记