繁体   English   中英

如何在将对象的构造函数更改为实例函数时保留 Javascript 对象的属性

[英]How do I retain the properties of a Javascript object while changing the object's constructor to an instance function

我在 javascript 中有一个实例函数,为了命名约定,我添加了其他实例函数作为第一个实例函数对象的属性。 下面的工作 JavaScript 更好地说明了这一点。

var MyModule = (function() { // instance function 
    return function() {
      console.log("ran MyModule");
    }
}());

MyModule.RelatedModule = (function() { //second instance function is a property of first instance function object
    return function() {
        console.log("ran RelatedModule");
    }
}())

var inst1 = new MyModule(), // logs "ran MyModule"
    inst2 = new MyModule.RelatedModule(); // logs "ran RelatedModule"

这按预期工作,没有错误。 我想做的是在创建MyModule对象后为MyModule创建函数定义,有人可以帮我实现吗? 我在下面说明了我的尝试。

var MyModule = {}; // create object first, try to set a constructor on it later

MyModule.RelatedModule = (function() { // add properties to the MyModule object
    return function() {
        console.log("ran RelatedModule");
    }
}())

// the following does not work, I'd like to set the `MyModule` constructor instance function and retain the `MyModule.RelatedModule` property
MyModule.constructor = (function() {
    return function() {
      console.log("ran MyModule");
    }
}());

那么,如何保留对象的属性并更改其构造函数呢?

你混淆了几个概念。 在您的第一个示例中, MyModule没有构造函数,它一个构造函数。 也就是说,它是一个函数对象,您打算与new运算符一起使用来创建新对象。 这些对象将具有指向MyModule (创建它们的函数)的constructor属性。 更改此constructor属性不会对MyModule产生任何影响; 该属性只是一个指向实例化对象的函数的指针。

换句话说,您不能更改MyModule的构造函数。 那是毫无意义的说法。

现在,当你写:

var MyModule = {};

...您创建一个新对象,其constructor属性为Object()

console.log(MyModule.constructor) // prints Object()

同样,更改此属性实际上并没有多大作用(除了混淆一些有用的簿记)。

此时MyModule只是一个普通的旧对象。 它根本不是一个函数。 这就是为什么您会收到“不是函数”错误的原因。 因为它不是,但你正试图像使用它一样使用它。 如果您希望该名称引用一个函数(即指向不同的对象),那么您将丢失对先前设置的任何属性的所有引用,因为您指向的是一个全新的对象

就是那样子。

现在,您可以保存对包含所有先前设置的属性的对象的引用,并在将该名称指向函数后将它们复制回MyObject 但我不确定重点是什么。

lwburk 所说的一切都是正确的,但是,下面的内容是您想要完成的,它通过调用MyModuleinit()方法来实现。

var MyModule = function(){
    return this.init();
};

MyModule.prototype.init = function(){};

MyModule.RelatedModule = (function() { // add properties to the MyModule object
    return function() {
       console.log("ran RelatedModule");
    };
}());

MyModule.prototype.init = function(){
   console.log("ran MyModule");
};

var inst1 = new MyModule(),
    inst2 = new MyModule.RelatedModule();

首先,存在一个已知的浏览器错误,其中(构造对象的)构造函数属性使用原型正确解析,但未应用于对象构造。 因此,您需要以下 polyfill:

function NEW(clas, ...args)
{
  let res = Object.setPrototypeOf({}, clas.prototype);
  res.constructor.apply(res, args);
  return res;
}

其次,您需要设置MyModule.prototype.constructor而不是MyModule.constructor 原因是MyModule.constructor是构造新的函数,而不是构造新对象的函数。 (请参阅: 为什么一个类在 JavaScript 中有一个“构造函数”字段?

换句话说:

var MyModule = {}; // create object first, try to set a constructor on it later

MyModule.RelatedModule = (function() { // add properties to the MyModule object
    return function() {
        console.log("ran RelatedModule");
    }
}())

// set the `MyModule` prototype.constructor instance function and retain the `MyModule.RelatedModule` property
MyModule.prototype = {
  constructor() {
      console.log("ran MyModule");
}}

var inst1 = NEW(MyModule), // logs "ran MyModule"
    inst2 = NEW(MyModule.RelatedModule); // logs "ran RelatedModule"

简短的回答是你不能这样做。 但是,您可以更改对象的原型。 查看此答案以深入了解如何重新考虑使用此约束的方法: Changing constructor in JavaScript

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM