JavaScript中函数的prototype原型的constructor的奇怪问题?
阿神
阿神 2017-04-10 16:29:00
0
2
406

JavaScript中函数的prototype原型对象的constructor为什么明明已经改过来了,但new出来的对象中的constructor却还是原来的?

具体请看下面的代码和注释:

function CreateObject(pPrototypeClass, pParams) { function Temp() { pPrototypeClass.Create.apply(this, pParams); alert('2.Temp.prototype.constructor: ' + Temp.prototype.constructor); //此时Temp.prototype.constructor为Temp函数本身 Temp.prototype = pPrototypeClass; alert('3.Temp.prototype.constructor: ' + Temp.prototype.constructor); //此时Temp.prototype.constructor已变为Object函数 }; alert('1.Temp.prototype.constructor: ' + Temp.prototype.constructor); //此时Temp.prototype.constructor为Temp函数本身 alert('pPrototypeClass.constructor: ' + pPrototypeClass.constructor); //pPrototypeClass.constructor为Object函数 return new Temp(); }; var PersonPrototypeClass = { Create: function(pName, pAge) { this.name = pName; this.age = pAge; }, SayHello: function() { alert("Hello, I'm " + this.name); }, HowOld: function() { alert(this.name + " is " + this.age + " years old."); } }; var oPerson = CreateObject(PersonPrototypeClass, ["Bill Gates", 53]); alert('oPerson.constructor: ' + oPerson.constructor); //这里oPerson.constructor却仍然是Temp函数!为什么?前面Temp.prototype.constructor不是已改为Object函数了吗? alert(oPerson.constructor == Object); //为false,按道理应该为true

但如果把Temp函数的这一句Temp.prototype = pPrototypeClass;移动到外层函数CreateObject中,如下:

function CreateObject(pPrototypeClass, pParams) { function Temp() { pPrototypeClass.Create.apply(this, pParams); alert('3.Temp.prototype.constructor: ' + Temp.prototype.constructor); //此时Temp.prototype.constructor已变为Object函数 }; alert('1.Temp.prototype.constructor: ' + Temp.prototype.constructor); //此时Temp.prototype.constructor为Temp函数本身 Temp.prototype = pPrototypeClass; alert('2.Temp.prototype.constructor: ' + Temp.prototype.constructor); //此时Temp.prototype.constructor已变为Object函数 alert('pPrototypeClass.constructor: ' + pPrototypeClass.constructor); //pPrototypeClass.constructor为Object函数 return new Temp(); }; var PersonPrototypeClass = { Create: function(pName, pAge) { this.name = pName; this.age = pAge; }, SayHello: function() { alert("Hello, I'm " + this.name); }, HowOld: function() { alert(this.name + " is " + this.age + " years old."); } }; var oPerson = CreateObject(PersonPrototypeClass, ["Bill Gates", 53]); alert('oPerson.constructor: ' + oPerson.constructor); //这里oPerson.constructor已变为Object函数 alert(oPerson.constructor == Object); //为true

为什么Temp.prototype = pPrototypeClass;这句语句在Temp函数体内和移动到外层函数体内,结果就不一样呢?

———————————————————————————————————————————
20151209补充:

感谢各位的回答,每位答主都从不同角度部分地解答了我的部分疑惑。现在我的看法是,关键在于new一个构造函数的时候,到底发生了什么?下面总结一下我现在的理解。new一个构造函数的时候,依次发生了如下三个步骤:

1)创建一个空的新对象。

2)将新对象的隐式原型属性__proto__赋值为构造函数的显式原型属性prototype,即新对象.__proto__ = 构造函数.prototype。

3)执行构造函数,并且同时将构造函数中的this指向新对象,即构造函数.call(新对象)。

因此,new一个构造函数时,是先将该构造函数的prototype赋值给新对象的__proto__,然后才执行构造函数;而不是先执行构造函数,然后才赋值prototype。这两个步骤的顺序,才是问题中前后两段代码的运行结果不同的原因。

再次感谢各位的回答!

阿神
阿神

闭关修行中......

全員に返信 (2)
小葫芦

这个结果不一样这是正常的,你放在里面的时候,在你n做new动作之前你还没有改变Temp.prototype,new 动作在之前,new temp 就是在操作prototype。你这个是没有变化的,另外new 动作之后 做Temp.prototype 只是动态改变了Temp.prototype的属性。constructor 还是Temp。

并且 就算你改变了Temp.prototype,你也没有返回 已经坐更改的Temp,当然此刻按照你的写法返回Temp 的实例 就是一个死循环了。 你可以断点跟踪一下 当你改变了Temp.prototype,然后再new出来的对象 已经发生了变化了

いいねを押す+0
    迷茫

    好长的代码啊,第一个oPerson.constructor指向的是Temp函数,你的疑惑应该是在Temp.prototype = pPrototypeClass;,不是将Temp.prototype更改了吗,但是事情并不是你想的这样的啊,你这样是将Temp.prototype赋值为了另外一个对象,这样就阻断了它与oPerson对象的关系,因为oPerson__proto__属性指向的仍然是你原来在堆中存的那个对象,来看下面这段代码你就会明白:

    function Temp () { this.name = "zp"; } Temp.prototype.age = 19; var obj = new Temp(); Temp.prototype = { age: 20 }; console.log(obj.__proto__); // {age: 19}

    下面那个为什么是true的原因也很简单,因为你在应用构造函数之前就将这个函数的原型地址给改了,你使用构造函数时,他们指向的一块内存。

    いいねを押す+0
      最新のダウンロード
      詳細>
      ウェブエフェクト
      公式サイト
      サイト素材
      フロントエンドテンプレート
      私たちについて 免責事項 Sitemap
      PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!