1
var someObject = function(arg) {
    this.property = function() {
        // do something with the argument
        return arg;
    }();
};

var obj = new someObject(some argument);
// object.property instanceof "someObject" should be true

当使用propertyof时,应该创建someObject一个新的实例。newObject例如,当我使用原生 DOM Element 的 nextSibling 属性时,会返回一个新的 DOM Element 对象实例。我想知道是否有可能创建一个类似的结构。或者这样会导致无限递归吗?

4

5 回答 5

1

严格来说,这在 ES5 中是可能的(所有最新的浏览器,是的,包括 IE)。

ES5 通过getandset关键字或Object.defineProperty函数指定 getter 和 setter,因此您可以使函数表现得像属性(想想 innerHTML)。以下是您的操作方法:

function Mother () {
    this.name = '';
    Object.defineproperty(this,'child',{
        get: function(){
            return new Mother();
        }
    });
}

所以对象现在可以简单地通过读取child属性来创建自己的新实例:

var a = new Mother();
a.name = 'Alice';
b = a.child;
b.name = 'Susan';

alert(a.name) // Alice
alert(b.name) // Susan

a instanceof Mother; // true
b instanceof Mother; // true

话虽如此,您对 DOM 元素的观察是错误的。DOM 只是一个树结构。您可以使用老式 javascript 自己创建类似的结构:

function MyObject () {}

var a = new MyObject();
var b = new MyObject();
var c = new MyObject();
a.children = [b,c];
b.nextSibling = c;
c.prevSibling = b;

// now it works like the DOM:
b.nextSibling; // returns c
a.children[1]; // returns c
b.nextSibling.prevSibling instanceof MyObject; // true
于 2013-10-23T13:18:37.643 回答
0

nextSibling不返回元素,它返回一个现有元素,它是目标元素的下一个兄弟元素。

您可以将对象引用存储为另一个对象的属性,就像您可以存储原始值一样。

function SomeObject(obj) {
    this.obj = obj;
}

var someObject = new SomeObject(new SomeObject());

someObject.obj instanceof SomeObject //true

但是,如果您想SomeObject在访问时动态创建一个新实例,someObject.obj或者您想根据每次访问属性时都应重新评估的条件返回现有对象,则需要使用函数或访问器

function SomeObject(obj) {
    this.obj = obj;
}

SomeObject.prototype.clone = function () {
    //using this.constructor is a DRY way of accessing the current object constructor
    //instead of writing new SomeObject(...)
    return new this.constructor(this.obj);
};

var someObject = new SomeObject(new SomeObject());
var someObjectClone = someObject.clone();

最后使用访问器(请注意,它们不是跨浏览器且无法填充

function SequentialObj(num) {
    this.num = num;
}

Object.defineProperty(SequentialObj.prototype, 'next', {
    get: function () {
        return new this.constructor(this.num + 1);
    },
    configurable: false
});

var seq = new SequentialObj(0);

console.log(seq.next); //SequentialObj {num: 1}
console.log(seq.next.next.next); //SequentialObj {num: 3}
于 2013-10-23T13:12:15.833 回答
0

您对 DOM 中的 nextSibling 属性的理解是不正确的。它不会创建新的 DOMElement,它只是引用现有的 DOM 节点。

当你创建一个你有引用的元素的兄弟时(例如,通过 jQuery 或 document.createElement),浏览器知道更新兄弟和父/子引用。

所以,你试图模仿的行为甚至不存在。

正如其他人所暗示的那样,仅访问对象上的属性不足以让 Javascript 解释器“做”任何事情(除了尊重您正在查找的名称)。您需要属性才能成为功能。

于 2013-10-23T12:51:51.750 回答
0

不,那是不可能的。您可以将函数设置为属性,但无论如何,您需要以某种方式调用函数(使用property()符号或使用call/apply),因为函数它本身就是一个对象,并且仅对解释()call/apply说您想要执行代码,但不仅可以访问到函数的对象数据。

于 2013-10-23T12:42:00.703 回答
-1

如果你想this.property()返回一个新的someObject,你可以编写如下的类:

var someObject = function(arg) {
    this.arg = arg;
};
someObject.prototype.property = function(arg) {
    // do something with the argument
    return new someObject(arg||this.arg);
}();

var obj = new someObject(/*some argument*/);
// object.property instanceof "someObject" should be true

如果您希望它返回一些已经实例化的版本,您可以编写如下代码:

var someObject = (function() {
    var previous;
    function(arg) {
        this.arg = arg;
        this.propertyBefore = previous;//refers to the someObject created before this one
        if(previous) previous.property = this; //before.property now references this class
        //this.property will be undefined until another instance of someObject is created
        previous = this;
    };
})()

var obj = new someObject(/*some argument*/);// returns someObject already created earlier (similar to nextSibling)

一个小笔记 - 在 javascript 中使用大写名称(SomeObject而不是someObject)声明类名的最佳实践

于 2013-10-23T12:46:18.560 回答