理解javascript原型和作用域系列(4)——隐式原型

上节已经提到,每个函数function都有一个prototype,即原型。这里再加一句话——每个对象都有一个__proto__,可成为隐式原型。

这个__proto__是一个隐藏的属性,javascript不希望开发者用到这个属性值,有的低版本浏览器甚至不支持这个属性值。所以你在Visual Studio 2012这样很高级很智能的编辑器中,都不会有__proto__的智能提示,但是你不用管它,直接写出来就是了。

上面截图看来,obj.__proto__和Object.prototype的属性一样!这么巧!

答案就是一样。

obj这个对象本质上是被Object函数创建的,因此obj.__proto__=== Object.prototype。我们可以用一个图来表示。

即,每个对象都有一个__proto__属性,指向创建该对象的函数的prototype。

那么上图中的“Object prototype”也是一个对象,它的__proto__指向哪里?

好问题!

在说明“Object prototype”之前,先说一下自定义函数的prototype。自定义函数的prototype本质上就是和 var obj = {} 是一样的,都是被Object创建,所以它的__proto__指向的就是Object.prototype。

但是Object.prototype确实一个特例——它的__proto__指向的是null,切记切记!

还有——函数也是一种对象,函数也有__proto__吗?

又一个好问题!——当然有。

函数也不是从石头缝里蹦出来的,函数也是被创建出来的。谁创建了函数呢?——Function——注意这个大写的“F”。

且看如下代码。

以上代码中,第一种方式是比较传统的函数创建方式,第二种是用new Functoin创建。

首先根本不推荐用第二种方式。

这里只是向大家演示,函数是被Function创建的。

好了,根据上面说的一句话——对象的__proto__指向的是创建它的函数的prototype,就会出现:Object.__proto__ === Function.prototype。用一个图来表示。

上图中,很明显的标出了:自定义函数Foo.__proto__指向Function.prototype,Object.__proto__指向Function.prototype,唉,怎么还有一个……Function.__proto__指向Function.prototype?这不成了循环引用了?

对!是一个环形结构。

其实稍微想一下就明白了。Function也是一个函数,函数是一种对象,也有__proto__属性。既然是函数,那么它一定是被Function创建。所以——Function是被自身创建的。所以它的__proto__指向了自身的Prototype。

篇幅不少了,估计也都看烦了。快结束了。

最后一个问题:Function.prototype指向的对象,它的__proto__是不是也指向Object.prototype?

答案是肯定的。因为Function.prototype指向的对象也是一个普通的被Object创建的对象,所以也遵循基本的规则。

OK 本节结束,是不是很乱?

乱很正常。那这一节就让它先乱着,下一节我们将请另一个老朋友来帮忙,把它理清楚。这位老朋友就是——instanceof。

具体内容,请看下节分解。

---------------------------------------------------------------------------

本文已更新到《理解javascript原型和作用域系列》的目录,更多内容可参见《理解javascript原型和作用域系列》。

另外,欢迎关注我的微博

也欢迎关注我的其他教程——别怕,都是免费的!

微软petshop4.0源码解读视频》《json2.js源码解读视频

--------------------------------------------------------------------------

时间: 2024-09-29 03:35:49

理解javascript原型和作用域系列(4)——隐式原型的相关文章

理解javascript原型和作用域系列(7)——原型的灵活性

在Java和C#中,你可以简单的理解class是一个模子,对象就是被这个模子压出来的一批一批月饼(中秋节刚过完).压个啥样,就得是个啥样,不能随便动,动一动就坏了. 而在javascript中,就没有模子了,月饼被换成了面团,你可以捏成自己想要的样子. 首先,对象属性可以随时改动. 对象或者函数,刚开始new出来之后,可能啥属性都没有.但是你可以这会儿加一个,过一会儿在加两个,非常灵活. 在jQuery的源码中,对象被创建时什么属性都没有,都是代码一步一步执行时,一个一个加上的. 其次,如果继承

构造函数、原型对象、实例、隐式原型的理解

(欢迎一起探讨,如果有什么地方写的不准确或是不正确也欢迎大家指点,最后留了一个疑问,欢迎各位大神来探讨~) PS: 内容中的__proto__可能会被markdown语法导致显示为proto. 建议将构造函数中的方法都定义到构造函数的原型中,由该构造函数创建的实例的方法都会指向同一个方法.(在内部声明的话,每创建一个实例都会重新实例化函数,每个实例中的函数的指向是不同的:如果定义在全局中,且有很多方法,这样毫无封装性可言.) 一.属性和方法 构造函数可以定义三种属性和方法: 对象属性/对象方法:

函数原型prototype以及对象的隐式原型__prot0__的基本了解

prototype原型: 一. 函数与对象的关系    1. 函数是对象的一种(函数是对象类型)        例: function fn1(){.........}           console.log(fn1 instanceof Object);           返回true,说明函数(fn1)是对象类型. 2. 对象是由函数创建的       例: var obj = new Object();           var arr = new Array(3);       

理解javascript原型和作用域系列(3)——prototype原型

既typeof之后的另一位老朋友! prototype也是我们的老朋友,即使不了解的人,也应该都听过它的大名.如果它还是您的新朋友,我估计您也是javascript的新朋友. 在咱们的第一节(理解javascript原型和作用域系列(1)——一切都是对象)中说道,函数也是一种对象.他也是属性的集合,你也可以对函数进行自定义属性. 不用等咱们去试验,javascript自己就先做了表率,人家就默认的给函数一个属性——prototype.对,每个函数都有一个属性叫做prototype. 这个prot

理解javascript原型和作用域系列(2)——函数和对象的关系

上文(理解javascript原型和作用域系列(1)——一切都是对象)已经提到,函数就是对象的一种,因为通过instanceof函数可以判断. var fn = function () { }; console.log(fn instanceof Object); // true 对!函数是一种对象,但是函数却不像数组一样——你可以说数组是对象的一种,因为数组就像是对象的一个子集一样.但是函数与对象之间,却不仅仅是一种包含和被包含的关系,函数和对象之间的关系比较复杂,甚至有一点鸡生蛋蛋生鸡的逻辑

理解javascript原型和作用域系列 - 目录【连载中...】

说明: 该教程绕开了javascript的一些基本的语法知识,直接讲解javascript中最难理解的两个部分,也是和其他主流面向对象语言区别最大的两个部分——原型和作用域,当然,肯定少不了原型链和作用域链.帮你揭开javascript最神秘的面纱. 为什么要偏偏要讲这两个知识点? 这是我在这么多年学习javascript的经历中,认为最难理解.最常犯错的地方,学习这两个知识点,会让你对javascript有更深层次的理解,至少理解了原型和作用域,就不能再算是javascript菜鸟了.另外,这

理解javascript原型和作用域系列(1)——一切都是对象

“一切都是对象”这句话的重点在于如何去理解“对象”这个概念. ——当然,也不是所有的都是对象,值类型就不是对象. 首先咱们还是先看看javascript中一个常用的函数——typeof().typeof应该算是咱们的老朋友,还有谁没用过它? typeof函数输出的一共有几种类型,在此列出: function show(x) { console.log(typeof(x)); // undefined console.log(typeof(10)); // number console.log(t

理解javascript原型和作用域系列(12)——简介【作用域】

前几节的文章请查阅<理解javascript原型和作用域系列> 提到作用域,有一句话大家(有js开发经验者)可能比较熟悉:"javascript没有块级作用域".所谓"块",就是大括号"{}"中间的语句.例如if语句: 再比如for语句: 所以,我们在编写代码的时候,不要在"块"里面声明变量,要在代码的一开始就声明好了.以避免发生歧义.如: 其实,你光知道"javascript没有块级作用域"是

理解javascript原型和作用域系列(6)——继承

为何用“继承”为标题,而不用“原型链”? 原型链如果解释清楚了很容易理解,不会与常用的java/C#产生混淆.而“继承”确实常用面向对象语言中最基本的概念,但是java中的继承与javascript中的继承又完全是两回事儿.因此,这里把“继承”着重拿出来,就为了体现这个不同. javascript中的继承是通过原型链来体现的.先看几句代码 以上代码中,f1是Foo函数new出来的对象,f1.a是f1对象的基本属性,f1.b是怎么来的呢?——从Foo.prototype得来,因为f1.__prot