重写prototype,构造器更改的原理剖析

本文探讨了在JavaScript中如何通过对象字面量重写prototype对象,导致constructor属性不再指向原构造函数的问题。文章详细解释了原型链的工作原理,并通过实例展示了属性查找过程,最后通过代码验证了constructor属性的变化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近看《JavaScript高级程序设计(第三版)》第六章面向对象的程序设计时,对其中的一段话,始终理解不了,在仔细读了几遍以及代码实验之后终于彻底搞清楚了,问题如下:

用一个包含所有属性和方法的对象字面量来重写整个原型对象,如下面的例子所示:

function Person(){};
Person.prototype={
	name:"Nicholas",
	age:29,
	job:"Software Engineer",
	sayName:function(){
		alert(this.name);
	}
};

在上面的代码中,我们将Person.prototype设置为等于一个以对象字面量形式创建的新对象。最终结果相同,但有一个例外:constructor属性不再指向Person了。前面曾经介绍过,每创建一个函数,就会同时创建他的prototype对象,这个对象也会自动获得constructor属性。而我们在这里使用的语法,本质上完全重写了默认的prototype对象,因此constructor属性也就变成了新对象的constructor属性(指向Object函数),不再指向Person函数。

以上是书中原话,一直想不明白到底是如何转变的。现把我想通的思路整理如下:

首先将重写Person.propotype的字面量形式改写如下:

<span style="background-color: rgb(255, 204, 102);">Person.prototype = new Object();</span>
Person.prototype.name = "Nicholas";
Person.prototype.age=29;
Person.prototype.job="Software Engineer";
Person.prototype.sayName = function(){alert(this.name);};
其次,理解两句话

1.prototype就是通过调用构造函数而创建的那个对象实例的原型对象。

2.每当代码读取某个对象的某个属性时,都会执行一次搜索,目标是具有给定名字的属性。搜索首先从对象实例本身开始。如果在实例中找到了具有给定名字的属性,则返回该属性的值;如果没有找到,则继续搜索指针指向的原型对象,在原型对象中查找具有给定名字的属性。如果在原型对象中找到了这个属性,则返回该属性的值。

可能大家到这已经明白怎么回事了,但为了更清楚,我们使用图和代码再次解释和验证一下。


var friend = new Person();

alert(friend.constructor==Object);//true

这里会输出Object的过程是先查找friend内有无prototype属性,若无查找friend的原型对象即Person.prototype,Person.prototype内无constructor属性,则继续寻找Person.prototype的原型对象即Object.prototype的constructor属性,为Object{}。

<!DOCTYPE html>
<html>

<head>
    <meta charset='UTF-8'/>
    <script type="text/javascript">
        function Person(){
        }
        Person.prototype = {
            name:"dx"
        };
        function Human(){
        };
        var person = new Person();
        var human = new Human();
        window.onload=function(){
            alert("person.constructor==Person:"+(person.constructor==Person));//false
            alert("person.constructor==Object:"+(person.constructor==Object));//true
            alert("human.constructor==Human:"+(human.constructor==Human));//true
            alert("human.constructor==Object:"+(human.constructor==Object));//false
            alert("Person.prototype的constructor是否来自本身:"+Person.prototype.hasOwnProperty("constructor"));//false
            alert("Human.prototype的constructor是否来自本身:"+Human.prototype.hasOwnProperty("constructor")); //true
        }
    </script>
</head>
<body>

</body>
</html>
因此书中提供了一种指定构造函数的方式,即在Person.prototype内定义属性constructor为Person。这样就不会再去Person.prototype的原型对象内去寻找constructor了,因为重新定义了constructor属性,因此也导致了它的[[Enumerable]]属性为true。

如有错误,敬请大家积极批评指证,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值