为什么不能从原型改变构造函数? [英] Why is it impossible to change constructor function from prototype?

查看:149
本文介绍了为什么不能从原型改变构造函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的例子。

  function Rabbit(){
var jumps =yes;
};
var rabbit = new Rabbit();
alert(rabbit.jumps); // undefined
alert(Rabbit.prototype.constructor); //完全输出函数Rabbit()的代码;

我想更改中的代码Rabbit()以便 var jumps 变为公共。我是这样做的:

  Rabbit.prototype.constructor = function Rabbit(){
this.jumps =没有;
};
alert(Rabbit.prototype.constructor); //再次输出函数Rabbit()的代码和new this.jumps =no;
var rabbit2 = new Rabbit(); //使用新构造函数创建新对象
alert(rabbit2.jumps); //但仍然输出undefined

为什么不能用这种方式更改构造函数中的代码?

解决方案

您无法通过重新分配到 prototype.constructor <来更改构造函数/ p>

发生的事情是 Rabbit.prototype.constructor 是指向原始构造函数的指针(函数Rabit(){...} ),以便'class'的用户可以从实例中检测构造函数。因此,当你尝试这样做时:

  Rabbit.prototype.constructor = function Rabbit(){
this.jumps =不;
};

您只会影响依赖于 prototype.constructor <的代码/ code>从实例动态实例化对象。



当你调用 new X 时,JS引擎不会引用 X.prototype .constructor ,它使用 X 作为构造函数, X.prototype 作为新创建的对象的原型。忽略 X.prototype.constructor



解释这个的好方法是实现我们自己的运营商。 (Crockford会很开心,也不会更新;)



  //`new `emulator // //不引用`.constructor`来表示没有使用prototype.constructor //在对象中实现一个新的函数make(ctorFun,argsArray){//附加到原型的新实例但是构造函数//尚未被调用。 const newInstance = Object.create(ctorFun.prototype); ctorFun.apply(newInstance,argsArray); return newInstance;} //如果创建一个实用程序函数来从实例创建,那么它使用//继承的`constructor`属性,你的更改会影响到。函数makeFromInstance(instance,argsArray){return make(instance.constructor, argsArray);} function X(jumps){this.jumps = jumps;} //翻转构造函数,看看它影响什么X.prototype.constructor = function(jumps){this.jumps =!jumps;} const xFromConstructorIsGood = make( X,[true]); const xFromInstanceIsBad = makeFromInstance(xFromConstructorIsGood,[true]); console.log({xFromConstructorIsGood,xFromInstanceIsBad});  



JS中的继承



帮助JS继承的库实现继承并依赖 prototype.constructor ,其精神如下:

  function extend(base,sub){

function surrogateCtor(){}
//将原型从基础复制到设置继承
surrogateCtor.prototype = base.prototype;
sub.prototype = new surrogateCtor();
//使用上面的技巧将构造函数属性设置为基础构造函数
//,让我们修复它
sub.prototype.constructor = sub;
}

您可以在上面的代码中看到,我们必须修复构造函数属性,因为它有时用于在您只有实例时创建实例化对象。但它不会影响实际的构造函数。请参阅我关于JS继承的帖子 http:// js-bits .blogspot.com / 2010/08 / javascript-inheritance-done-right.html



如何重新定义构造函数
如果你真的想要重新定义一个构造函数,只需执行

  //如果Rabbit上有任何自定义属性
//(或者有人称之为静态属性),它们不会被复制,你必须使用getOwnPropertyNames手动执行这个操作

//请参阅https://developer.mozilla.org / en-US / docs / Web / JavaScript / Reference / Global_Objects / Object / getOwnPropertyNames
var oldProto = Rabbit.prototype;
Rabbit = function(){...};
Rabbit.prototype = oldProto;


I have such example.

function Rabbit() {
    var jumps = "yes";
};
var rabbit = new Rabbit();
alert(rabbit.jumps);                    // undefined
alert(Rabbit.prototype.constructor);    // outputs exactly the code of the function Rabbit();

I want to change the code in Rabbit() so that the var jumps becomes public. I do it this way:

Rabbit.prototype.constructor = function Rabbit() {
    this.jumps = "no";
};
alert(Rabbit.prototype.constructor);    // again outputs the code of function Rabbit() and with new this.jumps = "no";
var rabbit2 = new Rabbit();             // create new object with new constructor
alert(rabbit2.jumps);                   // but still outputs undefined

Why is it not possible to change the code in constructor function this way?

解决方案

You cannot change a constructor by reassigning to prototype.constructor

What is happening is that Rabbit.prototype.constructor is a pointer to the original constructor (function Rabit(){...}), so that users of the 'class' can detect the constructor from an instance. Therefore, when you try to do:

Rabbit.prototype.constructor = function Rabbit() {
    this.jumps = "no";
};

You're only going to affect code that relies on prototype.constructor to dynamically instantiate objects from instances.

When you call new X, the JS engine doesn't reference X.prototype.constructor, it uses the X as the constructor function and X.prototype as the newly created object's prototype., ignoring X.prototype.constructor.

A good way to explain this is to implement the new operator ourselves. ( Crockford will be happy, no more new ;)

// `new` emulator
// 
// Doesn't reference `.constructor` to show that prototype.constructor is not used
// when istantiating objects a la `new`
function make(ctorFun, argsArray) {
  // New instance attached to the prototype but the constructor
  // hasn't been called on it.
  const newInstance = Object.create(ctorFun.prototype);
  ctorFun.apply(newInstance, argsArray);
  return newInstance;
}

// If you create a utility function to create from instance, then it uses the
// inherited `constructor` property and your change would affect that.
function makeFromInstance(instance, argsArray) {
  return make(instance.constructor, argsArray);
}

function X(jumps) {
  this.jumps = jumps;
}

// Flip the constructor, see what it affects
X.prototype.constructor = function(jumps) {
  this.jumps = !jumps;
}

const xFromConstructorIsGood = make(X, [true]);
const xFromInstanceIsBad = makeFromInstance(xFromConstructorIsGood, [true]);

console.log({
  xFromConstructorIsGood,
  xFromInstanceIsBad
});

Inheritance in JS

Libraries that help with JS inheritance implement inheritance and do rely on prototype.constructor with something in the spirit the following:

function extend(base, sub) {

  function surrogateCtor() {}
  // Copy the prototype from the base to setup inheritance
  surrogateCtor.prototype = base.prototype;
  sub.prototype = new surrogateCtor();
  // The constructor property is set to the base constructor
  // with the above trick, let's fix it
  sub.prototype.constructor = sub;
}

You can see that in the above code, we have to fix the constructor property because it's sometimes used to create instantiate an object when you only have an instance. but it doesn't affect the actual constructor. See my post about JS inheritance http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html

How to redefine a constructor If you really want to redefine a constructor, just do

// If Rabbit had any custom properties on it 
// (or static properties as some call it), they would not be copied, you'd have to do that manually using getOwnPropertyNames

// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames
var oldProto = Rabbit.prototype;
Rabbit = function() {...};
Rabbit.prototype = oldProto;

这篇关于为什么不能从原型改变构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆