6

我有一些测试课

TestKlass = (function() {

    function TestKlass(value) {
      this.value = value != null ? value : 'hello world';
      console.log(this.value);
    }

    return TestKlass;

})();

x = new TestKlass;
x instanceof TestKlass; (gives true)

我有新的空对象

y = {}
y instanceof Object

我可以找到任何方法来为y设置任何属性,比如这样

y.__proto__ = x.__proto__
y.constructor.prototype = x.constructor.prototype

为了得到这个结果

y instanceof TestKlass => true

==================================================== ==

升级版:

所以。我的主要目标是创建 CLONE 功能。现在我的解决方案对我有用。请看这段代码:

JavaScript JS 对象克隆

Object._clone = function(obj) {
  var clone, property, value;
  if (!obj || typeof obj !== 'object') {
    return obj;
  }
  clone = typeof obj.pop === 'function' ? [] : {};
  clone.__proto__ = obj.__proto__;
  for (property in obj) {
    if (obj.hasOwnProperty(property)) {
      value = obj.property;
      if (value && typeof value === 'object') {
        clone[property] = Object._clone(value);
      } else {
        clone[property] = obj[property];
      }
    }
  }
  return clone;
};

CoffeeScript JS 对象克隆

# Object clone
Object._clone = (obj) ->
  return obj if not obj or typeof(obj) isnt 'object'
  clone = if typeof(obj.pop) is 'function' then [] else {}

  # deprecated, but need for instanceof method
  clone.__proto__ = obj.__proto__

  for property of obj
    if obj.hasOwnProperty property
      # clone properties
      value = obj.property
      if value and typeof(value) is 'object'
        clone[property] = Object._clone(value)
      else
        clone[property] = obj[property]

  clone

现在你可以尝试这样做

A = new TestKlass
B = Object._clone(A)
B instanceof TestKlass => true

它适用于 Moz FF 13。但我认为它不是跨浏览器。并且proto已被弃用。

我认为没有通用的解决方案。但也许它会对某人有所帮助。

4

2 回答 2

1

obj instanceof SomeConstructor检查是否在 obj 的原型链中的任何位置找到 SomeConstructor。

如果要继承,则需要将 FirstConstructor 的 .prototype 设置为新创建的 SomeConstructor 对象。

SomeConstructor = function() {}
FirstConstructor = function() {}
FirstConstroctor.prototype = new SomeConstructor();

var y = new FirstConstroctor();
y instanceof FirstConstructor; // true
y instanceof SomeConstructor ; // true, it bubbles from FirstConstructor.__proto__ to SomeConstructor
于 2012-06-25T08:58:15.017 回答
1

也许您应该先阅读以下答案。您要实现的目标非常简单。但是,在我解释之前,让我们看看您的解决方案:

解决方案 1

y.__proto__ = x.__proto__;

我不建议这样做,因为该__proto__属性现已弃用上面的代码在Rhino中不起作用。

解决方案 2

y.constructor.prototype = x.constructor.prototype;

这是一个非常糟糕的解决方案。原因是y.constructoris 实际上y.__proto__.constructor,因为yis 一个对象y.__proto__Object.prototype. 这意味着这与您本质上是在y.constructor更改. 这可能会破坏您页面上的其他代码。我强烈反对这种做法。ObjectprototypeObject

解决方案3(我的解决方案)

您要做的只是更改对象的内部[[proto]]属性。由于没有跨平台的方式,所以我们需要使用 hack。一个简单的解决方案是创建一个具有所需__proto__属性的新对象,并在其上设置 getter 和 setter 以更改原始对象。如下所示:

function setPrototypeOf(object, prototype) {
    var constructor = function () {
        for (var key in object) {
            if (object.hasOwnProperty(key)) {
                (function (key) {
                    Object.defineProperty(this, key, {
                        get: function () {
                            return object[key];
                        },
                        set: function (value) {
                            object[key] = value;
                        },
                        enumerable: true
                    });
                }).call(this, key);
            }
        }
    };

    constructor.prototype = prototype;

    return new constructor;
}

在此之后,您需要做的就是:

y = setPrototypeOf(y, TestKlass.prototype);

这是一个工作小提琴

编辑:

您的克隆函数的问题在于它只克隆对象和数组。您忘记考虑也通过引用传递的函数。因此,当您克隆具有关闭对象内部状态的方法的对象时,该对象及其克隆将共享相同的内部状态。请参阅以下小提琴

function Value(value) {
    this.get = function () {
        alert(value);
    };
    this.set = function (newValue) {
        value = newValue;
    };
}

var a = new Value(5);
var b = Object._clone(a);
b.set(10);                // setting b to 10 also sets a to 10
a.get();                  // alerts 10, should alert 5

JavaScript 中绝对没有办法克隆对象的内部状态,因此在 JavaScript 中克隆对象和数组仅适用于不将闭包作为方法公开的对象。

要了解有关在 JavaScript 中克隆对象的问题的更多信息,请阅读此答案。单击以下链接以阅读 John Resig 的答案。

于 2012-06-25T09:11:11.290 回答