javascript原型详解

相信很多人都很困惑于javascript的原型系统,,在我刚开始接触javascript的原型系统的时候,我也非常困惑于它的结构,因为我以前都没有接触过这种基于原型的语言。javascript是一个基于原型的语言,虽然是以函数为第一等公民的语言,但也可以实现面向对象,那就是基于它的原型系统。

javascript原型之函数

现在我们来写一个函数

function A(){

}

这是一个内容为空的函数,但它真的内容为空吗?让我们来看下面一段代码

function A(){

}

console.log(A.toString());;//输出为function A() {}

我们知道,javascript里面的一切都是对象,函数也是,既然函数是对象那么就可以调用函数对象的方法,所以我试着调用了toString 方法,它输出了一个字符串,证明toString方法是存在的。那么toString 方法到底是存在在那里呢,不存在于函数体里,那么存在一个地方必然有toString的函数体且对象function A以某种方式获得了toString方法的调用权。。。

我百度了一下基于原型的语言的特征,基于原型的语言,必然有一个或着多个最初的对象,然后以后的对象都是由这些最初对象克隆过来的,也就是说,基于原型的语言中对象的生成是根据存在的对象来复制的。

好,那我们开始下一步的实验

function A(){

}
console.log(A.__proto__);//Function
console.log(A.prototype);//{}

我输出了Javascript对象所拥有的两个属性,这是javascript语言规定的两个属性_proto_属性指向对象构造函数的原型(不是很理解),prototype属性指向对象的原型。从结果看A函数构造函数的原型是Function,A函数自己的原型是{ }(同样不是很理解)

于是我又做了下面这个实验

Function.prototype.getName = function(){
    return "FunctionTest";
}

function A(){

}
console.log(A.__proto__ === Function.prototype);//true
console.log(A.getName());//FunctionTest

function B(){

}
console.log(B.__proto__ === Function.prototype);//true
console.log(B.getName());//FunctionTest

console.log(A.__proto__ === A.constructor.prototype);//true
//即函数作为对象它的构造函数为Function

我从另外的地方得知javascript里面有内建的Function和Object对象,于是我想着Function对象是否和function A 有些关联呢,当我看到第一条console.log语句返回true的时候,我知道我是正确的,于是我扩展了Function.prototype 给其中添加了getName方法,然后我在用函数A调用了这个方法返回FunctionTest,我又新建了函数B,也调用了这个方法,返回FunctionTest。

至此我知道了函数_proto属性的指向,指向其构造函数的原型,当对象A调用getName函数的时候,由于A对象没有getName函数,javascript会寻找对象A的_proto属性所对应对象,有则调用,没有则继续向上找。

函数的prototype属性我一开始始终没有找到与之对应的对象

console.log(A.prototype === Function.__proto__);//false
console.log(A.prototype === Function.prototype);//false
console.log(A.prototype === Object.__proto__);//false
console.log(A.prototype === Object.prototype);//false

后来我换了一种思考方式终于找到了

console.log(A.prototype.__proto__ === Object.prototype);//true
console.log(A.prototype.prototype);//undefined

而之后我又实验了

console.log(Function.prototype.__proto__ === Object.prototype);

所以最终所有的一切对象的内置函数比如toString都是在Object.prototype里的

然后我又有一个猜测
所有一切函数对象的内置函数比如call,apply都是Function.prototype里的,可以很容易的就验证,普通对象是不能调用call,apply的。

javascript原型之对象

我实验了如下的代码

function A(){
    this.getText = function(){
        return "Text";
    }
}

A.prototype.getName = function(){
    return "my god";
}

var i = new A();

console.log(i.getText());//Text
console.log(i.getName());//my god

然后我改了一下程序

function A(){
    this.getName = function(){
      return "Text";
    }
}

A.prototype.getName = function(){
    return "my god";
}

var i = new A();

console.log(i.getName());//Text
console.log(i.__proto__ === A.prototype);//true
console.log(i.prototype);//undefined

由上面的实验可知,由函数A作为构造函数,所克隆出来的普通对象i的_proto_属性指向函数A的原型(也就是prototype属性),且普通对象i的prototype属性是没有定义的。

当i调用getName函数时,由于i是由函数A克隆出来(大家还没忘记原型语言的特征吧,就是新的对象是由另一个已存在的对象克隆的)的,里面只用getText函数没有getName函数,于是javascript就会寻找i的_proto_属性,而i的proto属性所指向的其实就是A.prototype,所以javascript就在A.prototype里面找getName函数,找到了就调用。所以第二段代码中优先调用返回Text的那个getName函数。

javascript里面还有一种对象就是对象字面量,对象字面量的是否拥有Function.prototype或者Object.prototype的函数呢
请看实验

var a = {
    getName:function(){
        return "a";
    }
}
console.log(a.__proto__);//{}
console.log(a.prototype);//undefined

console.log(a.__proto__ === Object.prototype);//true

由于对象字面量不是由函数对象克隆的,所以没有Function.prototype里面的方法,因为a._proto_指向的是Object.prototype,这就说明javascript只能在a本身和Object.prototype里面找调用的函数。

总结

由上面以一些内容我们可以得出:

1.javascript函数调用顺序是查找对象的原型(即,对象的_proto_属性),一层一层的往上找,直到遇到该函数或者undefined才停止。

2.函数作为特殊的对象,它的原型是Function.prototype,能够调用Function.prototype里面的方法,而Function.prototype的原型又是Object.prototype,故而函数对象既能调用Function.prototype里面的方法,还能调用Object.prototype里面的方法,这就说函数对象即是“函数”又是对象。

3.普通对象的原型是其构造函数的原型(即,A.prototype),而A.prototype的原型是Object.prototype,所以,普通对象只能调用它本身和Object.prototype内的函数

4.对象字面量的原型是Object.prototype。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,794评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,050评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,587评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,861评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,901评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,898评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,832评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,617评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,077评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,349评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,483评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,199评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,824评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,442评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,632评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,474评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,393评论 2 352

推荐阅读更多精彩内容