在Brendan Eich设计Javascript时,借鉴了Self和Smalltalk这两门基于原型的语言。之所以选择基于原型的面向对象系统,是因为Brendan Eich一开始没有打算在JavaScript中加入类的概念,其设计初衷是为非专业的开发人员提供一个方便的工具,使其使用尽可能简单、易学。随着人们对网页要求的逐渐提高,对JavaScript这门语言的要求愈来愈高,开发人员也需要对这门语言有充足的了解。
中javascript中,对象的产生是通过原型对象而来的。
原型的解释
原型:为其他对象提供共享属性的对象
每个对象都有一个__proto__(又名:[[Prototype]])属性, 该属性指向原型对象,并从中继承数据、结构和行为。每个函数(函数也是对象)都有一个 prototype 属性,它指向的也是一个原型对象。
这里的
__proto__
和[[Prototype]]
两个名词,在一些文章中常常混用在一起,导致难以理解,这里对两者进行解释。__proto__译为隐式原型,又名[[Prototype]],它指向原型对象。官方 ECMAScript 规定了 prototype 是个隐式引用,但是民间浏览器开了口子,实现了一个属性
__proto__
,让实例对象可以通过__proto__
访问其原型对象。再后来官方只好向事实低头,将__proto__
属性纳入规范中。至于 [[Prototype]],是在浏览器打印才显示的,它和__proto__
是一个含义,只是浏览器厂商换了个马甲。而且我们能在开发者工具中查看到的 [[Prototype]](或__proto__
)是浏览器厂商故意渲染的一个虚拟节点。实际上并不存在该对象,所以 [[Prototype]] 属性既不能被for in
遍历,也不能被Object.key(obj)
查找出来。
查看对象的__proto__属性
const obj = {}; // target.__proto__、Object.getPrototypeOf(target)等可以访问对象的[[Prototype]]属性 console.log('obj', Object.getPrototypeOf(obj));
输出对象obj,查看其__proto__属性。
Object.getPrototypeOf(target)直接访问对象的__proto__属性
查看函数的prototype属性
console.log('String', String.prototype);
从 ECMAScript 6 开始,
__proto__
属性被废除(__proto__是一个访问器属性,getter 函数和setter函数),因为该属性可以这个改变对象的原型,这是一个非常慢且影响性能的操作,使用这种方式来改变和继承属性是对性能影响非常严重的。推荐使用Object.getPrototypeOf
/Reflect.getPrototypeOf
和Object.setPrototypeOf
/Reflect.setPrototypeOf
(尽管如此,设置对象的 [[Prototype]] 是一个缓慢的操作,如果性能是一个问题,应该避免)。
小结
原型、原型对象(__proto__、[[Prototype]])、原型属性(prototype)其实是一个东西的不同称呼。当我们称呼这个东西为原型时,想表达的是它有什么作用,继承数据、结构和行为;当我们称它为原型对象时,是因为每个对象在其创建时会自带 __proto__/[[Prototype]] 属性,并指向这个对象的原型(对象);当我们称它为原型属性时,是因为每个函数都会在创建时自带 prototype 属性,而且这个属性是个指针,指向了原型对象。
标签:__,proto,对象,Javascript,原型,Prototype,属性 From: https://www.cnblogs.com/yoyo1216/p/17305306.html