-
Notifications
You must be signed in to change notification settings - Fork 124
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
深度解析原型中的各个难点 #2
Comments
Function.__proto__.__proto__ === Object.prototype |
只有总结看懂了 |
|
|
为什么置顶图只显示了一半......就是要这样吗? |
@Daoma666 你网络问题吧 |
@KieSun 可能是,但我也不知道什么原因,从掘金过来的,两个网站上图片都显示一半,但网页已经加载完了。。。 |
我这边也是一半 😂 |
@Daoma666 @MLuminary http://www.mollypages.org/tutorials/js.mp 这里有图,如果这里也显示不正确就没办法了 😂 |
@KieSun OK,这个显示正常 |
文中有很多的_proto_,是不是应该改成两个下划线__proto__? |
javascript 中的根对象是 Object.prototype 对象----《Javascript设计模式与编程实践》 |
感觉Function的原型对象是object |
赞,弄明白了。 |
感觉面试可以吹一波 |
这个为啥是false呢 |
虽然看一遍觉得讲的很清楚,但是还需要反复琢磨一下。 |
都懂啦~ 万分感谢 |
讲的很清楚 |
自己实现的new有个小小的细节问题: 如果Con构造函数返回的是null,那么这个函数最终返回的是null,然而这与实际的new操作符是不符的,实际的new操作符是会把创建的对象返回的,例如:
所以最后那个返回代码的判断是不是要改成: |
有一个实例a,a.proto.constructor.prototype..constructor.prototype..constructor.prototype......,里面出现了环形引用。这是历史遗留问题还是? |
战略性mark |
[].proto.constructor.proto === Function.prototype |
我读了3遍,才知道讲的啥。好惨 |
赞一个,完全看懂了 |
总结的第三点表示不敢苟同,所有的原型都是引擎创造的,只不过使用 proto 属性连起来了,并且对象的原型也就是顶级原型只是最先创造出来了而已。如果 Function 是女娲,那对象原型(对象的共有属性和方法组成的对象)就是伏羲,他们两个是祖先,Function 又创造了 Number、String、Boolean、Array、Object,这些构造函数都是 Function 的实例;而数字原型、字符串原型、布尔原型、数组原型、函数原型只是使用 proto 属性继承了对象原型的属性和方法。若要问为什么 Function.proto === Function.prototype,这只是 JS 之父在强行圆满罢了,事实上 Function 只是一个祖先,一个构造函数,并不是一个实例出来的函数对象,所以本来没必要拥有 proto 这个属性,但是这样的话会显得 Function 很另类,于是 JS 之父索性又给 Function 添加了一个 proto 属性,并指向函数原型,这就有了 Function.proto === Function.prototype,而 Function 创造了 Function 本身根本站不住脚的。 |
mark |
上帝(引擎)创造了亚当(Object.prototype),怕亚当太孤单,用他的肋骨创造了夏娃(Function.prototype,Function.prototype.proto === Object.prototype) |
大大流弊,讲得超清晰,学到啦 |
因为你的Fn返回的 |
Object.create(null)此时创建的对象是不存在__proto__的。 |
手写new那边,什么情况下,构造函数会主动返回一个对象 |
?????郛贍?,?栁?????!????~??lt;/FONT>??鯢??????????http://mvfin.cn
|
本文不会过多介绍基础知识,而是把重点放在原型的各个难点上。
大家可以先仔细分析下该图,然后让我们进入主题
prototype
首先来介绍下
prototype
属性。这是一个显式原型属性,只有函数才拥有该属性。基本上所有函数都有这个属性,但是也有一个例外如果你以上述方法创建一个函数,那么可以发现这个函数是不具有
prototype
属性的。prototype 如何产生的
当我们声明一个函数时,这个属性就被自动创建了。
并且这个属性的值是一个对象(也就是原型),只有一个属性
constructor
constructor
对应着构造函数,也就是Foo
。constructor
constructor
是一个公有且不可枚举的属性。一旦我们改变了函数的prototype
,那么新对象就没有这个属性了(当然可以通过原型链取到constructor
)。那么你肯定也有一个疑问,这个属性到底有什么用呢?其实这个属性可以说是一个历史遗留问题,在大部分情况下是没用的,在我的理解里,我认为他有两个作用:
xx.constructor.method
来扩展_proto_
这是每个对象都有的隐式原型属性,指向了创建该对象的构造函数的原型。其实这个属性指向了 [[prototype]],但是 [[prototype]] 是内部属性,我们并不能访问到,所以使用
_proto_
来访问。因为在 JS 中是没有类的概念的,为了实现类似继承的方式,通过
_proto_
将对象和原型联系起来组成原型链,得以让对象可以访问到不属于自己的属性。实例对象的
_proto_
如何产生的从上图可知,当我们使用
new
操作符时,生成的实例对象拥有了_proto_
属性。所以可以说,在
new
的过程中,新对象被添加了_proto_
并且链接到构造函数的原型上。new 的过程
在调用
new
的过程中会发生以上四件事情,我们也可以试着来自己实现一个new
对于实例对象来说,都是通过
new
产生的,无论是function Foo()
还是let a = { b : 1 }
。对于创建一个对象来说,更推荐使用字面量的方式创建对象。因为你使用
new Object()
的方式创建对象需要通过作用域链一层层找到Object
,但是你使用字面量的方式就没这个问题。Function.proto === Function.prototype
对于对象来说,
xx.__proto__.contrcutor
是该对象的构造函数,但是在图中我们可以发现Function.__proto__ === Function.prototype
,难道这代表着Function
自己产生了自己?答案肯定是否认的,要说明这个问题我们先从
Object
说起。从图中我们可以发现,所有对象都可以通过原型链最终找到
Object.prototype
,虽然Object.prototype
也是一个对象,但是这个对象却不是Object
创造的,而是引擎自己创建了Object.prototype
。所以可以这样说,所有实例都是对象,但是对象不一定都是实例。接下来我们来看
Function.prototype
这个特殊的对象,如果你在浏览器将这个对象打印出来,会发现这个对象其实是一个函数。我们知道函数都是通过
new Function()
生成的,难道Function.prototype
也是通过new Function()
产生的吗?答案也是否定的,这个函数也是引擎自己创建的。首先引擎创建了Object.prototype
,然后创建了Function.prototype
,并且通过__proto__
将两者联系了起来。这里也很好的解释了上面的一个问题,为什么let fun = Function.prototype.bind()
没有prototype
属性。因为Function.prototype
是引擎创建出来的对象,引擎认为不需要给这个对象添加prototype
属性。所以我们又可以得出一个结论,不是所有函数都是
new Function()
产生的。有了
Function.prototype
以后才有了function Function()
,然后其他的构造函数都是function Function()
生成的。现在可以来解释
Function.__proto__ === Function.prototype
这个问题了。因为先有的Function.prototype
以后才有的function Function()
,所以也就不存在鸡生蛋蛋生鸡的悖论问题了。对于为什么Function.__proto__
会等于Function.prototype
,个人的理解是:其他所有的构造函数都可以通过原型链找到Function.prototype
,并且function Function()
本质也是一个函数,为了不产生混乱就将function Function()
的__proto__
联系到了Function.prototype
上。总结
Object
是所有对象的爸爸,所有对象都可以通过__proto__
找到它Function
是所有函数的爸爸,所有函数都可以通过__proto__
找到它Function.prototype
和Object.prototype
是两个特殊的对象,他们由引擎来创建new
出来的prototype
是一个对象,也就是原型__proto__
指向原型,__proto__
将对象和原型连接起来组成了原型链The text was updated successfully, but these errors were encountered: