这两种对象构造方法之间的区别是什么?

时间:2015-02-13 12:43:50

标签: javascript

编写一些代码,我想做类似的事情:

var text = Text('hello').trim().bold();

所以,我做了以下事情。

function Text(text) {
    this.value = text;

    this.trim = function() { /* trim code */ return Text(this.value); }
    this.bold = function() { /* bold code */ return Text(this.value); }

    return this;
}

这与以下内容有何不同?

function Text(text) {
    this.value = text;

    this.trim = function() { /* trim code */ return new Text(this.value); }
    this.bold = function() { /* bold code */ return new Text(this.value); }
}

使用以下内容调用它?

var text = new Text('hello').trim().bold();

或者它们是否有效等效?

5 个答案:

答案 0 :(得分:2)

这里的基本观点是,在给定Text的实现 时,这一行是错误的:

var text = Text('hello').trim().bold();

...因为在Textthis存储了Text的属性,但当您按照上面的方式调用this时,undefined或者是全局对象(在松散模式下)或value(在严格模式下)。在松散模式下,您创建/覆盖名为trimboldundefined全局(因为您正在向全局对象写入属性,并且全局对象的所有属性都是全局的);在严格模式下,您会收到异常,因为您无法将属性分配给var text = new Text('hello').trim().bold(); // Note ---^^^

相反,你必须这样称呼它:

trim

这应该回答您关于boldnew的问题(例如,您需要第二个版本,即使用return this;的版本)。另外,如果使用new调用函数,则最后Text是不必要的。

如果你想在不使用new的情况下调用new,你可以,但实现必须不同 - 它必须创建它返回的对象,因为function makeText(text) { var obj = {}; obj.value = text; obj.trim = function() { /* trim code */ return makeText(this.value); }; obj.bold = function() { /* bold code */ return makeText(this.value); }; return obj; } 不是这样做:

function makeText(text) {
    return {
        value: text,
        trim: function() { /* trim code */ return makeText(this.value); },
        bold: function() { /* bold code */ return makeText(this.value); }
    };
}

或更简洁:

new

注意我更改了名称,因此它不再以大写字母开头;在JavaScript中,压倒性的约定是以大写字母开头的函数是构造函数(在正常情况下通过{{1}}调用的函数)。

答案 1 :(得分:1)

存在根本区别。第一种方法是使用共享实例。

function Text(text) {
    this.value = text;

    this.trim = function() { /* trim code */ return Text(this.value); }
    this.bold = function() { /* bold code */ return Text(this.value); }

    return this;
}
var text = Text('hello').trim().bold();
var text2 = Text('hello2').trim().bold();

alert(text.value);

这将输出'hello2'(jsfiddle

while:

function Text(text) {
    this.value = text;

    this.trim = function() { /* trim code */ return new Text(this.value); }
    this.bold = function() { /* bold code */ return new Text(this.value); }
}

var text = new Text('hello').trim().bold();
var text2 = new Text('hello2').trim().bold();

alert(text.value);

将按照预期输出'hello'。 (jsfiddle

我认为你真正打算做的是:(jsfiddle

function Text(text) {
    this.value = text;

    this.duplicate = function() { 
         this.value = this.value+this.value; 
         return this; 
    }
    this.bold = function() { 
         this.value = "<b>"+this.value+"</b>"; 
         return this; 
    }
}

var text = new Text('hello').duplicate().bold();
var text2 = new Text('hello2').duplicate().bold();

alert(text.value);

答案 2 :(得分:0)

我认为最好将此方法添加到标准的Javascript String对象中,例如javascript: add method to string class

答案 3 :(得分:0)

当使用new调用时没有区别,构造函数隐式返回this

如果在没有new的情况下调用这些函数,则第一个函数将返回全局上下文,而第二个函数将返回undefined

答案 4 :(得分:0)

如果要为后续调用实现链接,您将要执行的操作如下所示。

function Text(text) {
    this.value = text;

    this.trim = function() { /* trim code */ return this; }
    this.bold = function() { /* bold code */ return this; }
}

话虽如此,我想解释一下你的两个代码在做什么。

在你的第一个代码中。您正在调用没有new关键字的构造函数,这使得默认上下文传递为this,即窗口。所以你有效地在窗口上添加属性,并且调用的第二个方法.bold()将在窗口上,因为你从.trim()返回相同的对象。

在您的第二个代码中,当您说new Text时实际上是在创建新对象,因此您丢失了之前已调用.trim()方法的对象,并且第二次调用.bold是对从.trim()返回的新对象进行了制作。