【Web前端问题】一个关于JavaScript中作用域链的问题,prototype 和 __proto__ 的区别?
请看代码
代码一
<script type="text/javascript">var animal = function(){};
var dog = function(){};
animal.price = 2000;
dog.__proto__ = animal;
var tidy = new dog();
console.log(dog.price) //2000
console.log(tidy.price) // undefined
</script>
代码二
<script type="">var animal = function(){};
var dog = function(){};
animal.price = 2000;
dog.prototype = animal;
var tidy = new dog();
console.log(dog.price) //undefined
console.log(tidy.price) // 2000
</script>
为什么结果是相反的?
JavaScript中基于原型链的继承是怎么样的?
回答:
__proto__
是实例(如 tidy)访问原型对象,同时它是非标准的,ES5 标准方法是 Object.getPrototypeOf()
prototype
是构造函数(如 Dog) 访问原型对象
可以这样验证
function Dog() {}var tidy = new Dog();
// 它们引用的是同一个内存地址,即它们的原型。
tidy.__proto__ === Dog.prototype
但是到这里并没有体现基于原型链的继承
function Dog() {}function Animal() {}
// 实现原型链继承
Dog.prototype.__proto__ = Animal.prototype;
var tidy = new Dog();
// tidy 的原型指向 Dog.prototype
tidy.__proto__ === Dog.prototype
// 因为 Dog.prototype.__proto__ === Animal.prototype
// tidy 的原型的原型(形成原型链)指向 Animal.prototype
tidy.__proto__.__proto__ === Animal.prototype
// 原型链的终端是 Object.prototype
tidy.__proto__.__proto__.__proto__ === Object.prototype
// 再往前就是 null 了
tidy.__proto__.__proto__.__proto__.__proto__ === null
回答:
又有人问这个问题了,__proto__
本质上其实是标准里规定的[[prototype]]
属性,原本是不可用 js 访问的,后来(据说标准里又规定可以)firefox 和 chrome 中把这个属性命名为__proto__
。后来ES
又添加了函数getPrototypeof
,这样就可以通过这个函数来访问这个属性,所以这个__proto__
现在不是标准的一部分。
然后,再说new
的创建过程,当执行new func()
的时候,执行过程如下:
1、首先创建一个新的对象,比如叫 obj
;
2、obj.[[prototype]] = func.prototype
;
3、令this=obj
,执行函数 func
;
4、如果 func
的返回值是一个对象,则 new
的返回值就是这个对象,否则返回值是 obj
当 __读取__(注意是读取)对象的属性的时候,返回值是:
if(obj.prop) return obj.prop
else if(obj.[[prototype]].prop)
return obj.[[prototype]].prop;
else if(obj.[[prototype]].[[prototype]].prop)
return obj.[[prototype]].[[prototype]].prop;
//......一直这样找下去
else { return undefined;}
如下图:
var Fish = new Function(){} //等价于
var Fish = function(){}
回答:
根据上面大神的解释,我总结了一下,作用域链的指向如下
以下代码可以直接运行,大家可以试一下
代码一
<script type="text/javascript">var animal = function(){};
var dog = function(){};
animal.price = 2000;
dog.__proto__ = animal;
var tidy = new dog();
console.log(dog.__proto__ === animal) //true
console.log(dog.__proto__.__proto__ === animal.__proto__) //true
console.log(dog.__proto__.__proto__.__proto__ === Object.prototype) //true
console.log(dog.__proto__.__proto__.__proto__.__proto__ === null) //true
console.log(tidy.__proto__ === dog.prototype) //true
console.log(tidy.__proto__.__proto__ === dog.prototype.__proto__) //true
console.log(tidy.__proto__.__proto__ === Object.prototype) //true
console.log(tidy.__proto__.__proto__.__proto__ === null) //true
console.log(dog.price) //2000
console.log(tidy.price) // undefined
</script>
代码二
<script type="text/javascript">var animal = function(){};
var dog = function(){};
animal.price = 2000;
dog.prototype = animal;
var tidy = new dog();
console.log(tidy.__proto__ === dog.prototype) //true
console.log(tidy.__proto__.__proto__ === animal.__proto__) //true
console.log(tidy.__proto__.__proto__.__proto__ === Object.prototype) //true
console.log(tidy.__proto__.__proto__.__proto__.__proto__ === null) //true
console.log(dog.__proto__ === Function.prototype) //true
console.log(dog.__proto__.__proto__ === Object.prototype) //true
console.log(dog.__proto__.__proto__.__proto__ === null) //true
console.log(dog.price) //undefined
console.log(tidy.price) // 2000
</script>
回答:
tidy是对象,而dog是function。可以这么理解,prototye指定类型(函数)基类,而__proto__获得对象的原型链
回答:
function 拾人牙慧(){
//我觉得重点在于理解下面这段语句:
var tidy = new dog();
//即
tidy.__proto__ === dog.prototype;
}
另外dog.prototype = animal; 是不会影响原dog()函数中的属性。
而dog.__proto__指向了animal,所以dog.price继承了animal.price
不知道理解是否得当,有错误请指出。
以上是 【Web前端问题】一个关于JavaScript中作用域链的问题,prototype 和 __proto__ 的区别? 的全部内容, 来源链接: utcz.com/a/142917.html