1
记一次研究原型和错误理解的经历

最终得出的结论 原型链查找方式 就是:

自身-->原型对象-->原型对象的原型对象-->...-->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

shuhdad
15 声望2 粉丝