记一次研究原型和错误理解的经历
最终得出的结论 原型链查找方式 就是:
自身-->原型对象-->原型对象的原型对象-->...-->null 结束
比如下面的例子
Function.prototype.color = 'F-color'
var func = function(){};
var fo = new func();
此时访问
1.func.color
首先在func自身属性查找,未查到,再去其原型对象 func.__prototype
中去查找 func的构造函数为Function,那么也就是去Function.prototype中去找,找到了color 并返回
> func.color
< 'F-color'
2.fo.color
首先在fo
自身属性查找,未找到,再去其原型对象 fo.__prototype__
中去找, fo
的构造函数 是 func
,也就是去func.prototype
中去找,仍未找到,则去该原型对象的原型对象 也就是 func.prototype.__prototype__
,那是什么呢,
来分析下,func.prototype
是什么?是一个原型对象,一个object,其构造函数应该是Object,那么也就是 Object.prototype
,那么我们并未扩展Object的原型对象,所以仍找不到,再后面,就是null(Object.prototype.__prototype__
)了,宣告查询无果,返回undefined
一开始,我想当然的,是fo
-->fo.__prototype__
即 func.prototype
找不到 则 --> func.__prototype__
(这一步错了)
应该是-->func.prototype.__prototype__
这里讲解的很到位mdn
另外在研究原型链之初,对构造函数做了研究 构造函数的理解
附上 2道题
题1
var A = function() {}
A.prototype.n = 1
var b = new A()
A.prototype = {
n: 2,
m: 3
}
var c = new A()
console.log(b.n, b.m, c.n, c.m) //1,undefined,2,3
题2
var F = function(){};
Object.prototype.a = function(){
console.log('a()')
};
Object.prototype.b = function(){
console.log('bo()')
};
Function.prototype.b = function(){
console.log('bf()')
};
var f = new F();
f.a();//'a()'
f.b();//'bo()'
F.a();//'a()'
F.b();//'bf()'
在弄懂了之前的问题后,解这2道题 就轻松多了
1.
b的 原型 b.__prototype__
指向 为A 的prototype 指向的旧地址
c的 原型 c.__prototype__
指向 为A 的prototype 指向的新地址
2.和文中一开始解释的问题一个类型,f的原型对象找不到, 会找该原型对象的原型对象即 Object
Object.create(someObject)
回顾在上面一个问题func.prototype.__prototype__
推论出是Object.prototype ,给出的解释是因为其是一个对象,这么说其实不严谨,准确来说,应该是func.prototype.__prototype__
是一个原型为Object.prototype的对象。因为并非所有对象,他们的直接上级原型都是Object.prototype
不然,哪有什么自定义继承了呢,不就都直接继承Object了吗
ECMAScript 5 中引入了一个新方法:Object.create()。可以调用这个方法来创建一个新对象。新对象的原型就是调用 create 方法时传入的第一个参数
可以看出传入的对象,本身被作为 新对象的 原型对象,即newObject.__prototype = someObject
var objsource = {name:'shuhdad',age:'27'};
var newObj = Object.create(objsource);
> newObj
< {}
> newObj.name
< 'shuhdad'
> newObj.__prototype
< {name: "shuhdad", age: "27"}
这样可以看出传入的objsource 是他的原型链,所以看起来是继承的样子。
此时的newObj原型链 是什么样呢?
newObj --> objsource --> Object --> null
可以看出,虽然newObj 是一个对象,但是并不能直接推论出他的原型对象就是Object.prototype,中间可能经过了其他原型对象再到Object.
使用下面的打印,来判断是否有理解
var objsource = {name:'shuhdad',age:'27'};
var newObj = Object.create(objsource);
var newObje2 = Object.create(newObj);
> newObje2.__proto__ === newObj
< true
> newObje2.__proto__.__proto__ === objsource
< true
> newObje2.__proto__.__proto__.__proto__ === Object.prototype
< true
此时访问newObj2的原型链 为
newObje2 --> newObj -->objsource -->Object --> null
Object.create(null) 怎么解释?
它并不是创建一个null对象,而是创建一个没有原型的对象,
比如
var noprotoObj = Object.create(null);
访问noprotoObj的原型链为:
noprotoObj --> null
他可没有继承Object,也就没有hasOwnProperty方法
hasOwnProperty
遍历对象的属性时,原型链上的每个可枚举属性都会被枚举出来。
要检查对象是否具有自己定义的属性,而不是其原型链上的某个属性,则必须使用所有对象从 Object.prototype 继承的 hasOwnProperty 方法
比如上面的newObj 的例子
> newObj.hasOwnProperty('name')
< false
> objsource.hasOwnProperty('name')
< true
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。