2012-09-24 90 views
1

究竟是在JavaScript构造Return语句

function ObjA() { 
    this.a = 'text'; 
} 

var obj = new ObjA(); 

function ObjB() { 
    return { 
    a: 'text' 
    }; 
} 

var obj = new ObjB(); 

我这么问是因为我读this question,我已经注意到了一个答案下面的区别:

function Test() { 
    this.a = 1; 

    return { 
    get A() { return this.a; }, 
    set A(v) { this.a = v; } 
    }; 
} 

所以我问自己,这和以下有什么区别:

function Test() { 
    this.a = 1; 
} 

Test.prototype = { 
    get A() { return this.a; }, 
    set A(v) { this.a = v; } 
}; 

他们说,在评论认为,昔日的“猪内存作为getter和setter是‘独一无二’的每次每个对象”。有人能详细说明吗?

+5

这里真的有两个完全不同的问题;前两件事情以不同于第二件事的方式彼此不同。在第二对中,你的第二个例子实际上不起作用。构造函数内的'var'不会**成为对象属性。它不得不说'this.a = 1;'。 – Pointy

+0

http://stackoverflow.com/questions/2938940/return-statement-in-js-constructors?rq=1 –

+3

请问,你能改变名字吗?调用一个类“Object”就像是最糟糕的事情。 – Prinzhorn

回答

1

您实际上是在问几个不同的问题。因此,让我集中精力放在了第一位(修改变量名,以更轻松地引用他们,而不是覆盖Object):

究竟有什么区别:

function ObjA() { 
    this.a = 'text'; 
} 

var objA = new ObjA(); 

function ObjB() { 
    return { 
    a: 'text' 
    }; 
} 

var objB = new ObjB(); 

区别在于前一版本保持原型链,而后一版本将其丢弃。考虑下面的代码行:

ObjA.prototype.b = "something"; 
ObjB.prototype.b = "something"; 

然后会出现以下情况:

objA.b; //is "something" 
objB.b; //is undefined 

的原因是对象从“构造”返回不追加ObjB的原型链。这是一个全新的对象。这就是“差异”。

第二个例子(使用.prototype与返回对象)实际上并不真正“浪费”内存据我所知(请参见更新)。因为调用函数new运算符的过程将创建对象原型的副本,然后调用其函数。好的部分是,当你使用.prototype时,原型方法将在“构造函数”函数中可用,并且你将维护该版本的原型链。但我不知道使用基于回归的方法有什么“错误”。

UPDATE:

我签出的ECMAScript规范的主体(上油了我的思维齿轮位),看来,我是错的内存消耗。它看起来像“类”函数的原型属性的方法/属性通过引用链接。所以它实际上浪费了一些内存来生成一个新的对象,而不是使用原型。此外,返回对象中声明的任何属性都是实例级别的,而在原型对象中声明的属性对于“类”是静态的(即,由所有实例共享)。

正如其他人所指出的,您的示例有一个小错误(a不适用于原型对象)。但这对于手头的问题来说并不重要,所以我忽略了它。(我看你修正了这个错误)。

0

允许你创建一个没有私有方法的对象/功能(simulatory但它是)

function Object() { 
     // a can be change via OBJECTs API 
     this.a = 7; 
    } 

允许使用函数和变量,以“内部工作”该不会是在代码

function Object() { 
     // b CAN BE CHANGED FROM OBJECTs API 
     var b = 125;   
     return { 
     a: 7+b 
     }; 
    } 
1

访问你的最后一个例子不起作用。

function Test() { 
    var a = 1; 
} 

Test.prototype = { 
    // This code has no clue what a is 
    get A() { return a; }, 
    set A(v) { a = v; } 
}; 

但如果它是

function Test() { 
    this.a = 1; 
} 

Test.prototype = { 
    get A() { return this.a; }, 
    set A(v) { this.a = v; } 
}; 

然后代码的两片将是相似的,不同之处在于使用Test.prototype所述一个创建的Test一个实例,其中第一实施例(模块图案),总是通过使用工厂方法创建基本类型Object的某些东西

+0

是的,你是对的......我写这个问题很匆忙,没有注意到。 – Korikulum

0
function Object() { 
    this.a = 'text'; 
} 
var obj = new Object(); 

function Object() { 
    return { 
    a: 'text' 
    }; 
} 
var obj = new Object(); 

将分别用于像:

console.log(obj.a); // 'text' 

然而,

function Test() { 
    var a = 1; 

    return { 
    get A() { return a; }, 
    set A(v) { a = v; } 
    }; 
} 
var obj = new Test(); 

将用于像

console.log(obj.A); // 1 
obj.A = "banana"; 
console.log(obj.A) // 'banana' 

它正在a私人,并创建一个外部物业Aget/set它。这样做的好处是,它可以让你创建属性staticreadonly,获取/设置时进行计算以及其他许多事情。

1

的差异

之间
function Obj() { 
    this.a = 'text'; 
} 

var obj = new Obj(); 

function Obj() { 
    return { 
    a: 'text' 
    }; 
} 

var obj = new Obj(); 

是,第一个被认为是不安全的。这就是说,如果您忘记使用new运算符,则会污染具有属性的全局名称空间。

定义对象的第二种方法好得多。你们都可以做var obj = new Obj();var obj = Obj();,结果会完全一样。

此外,在构造函数中使用var将导致它们不能从构造函数本身的范围之外访问。因此,你可以用它们作为私人,定义工作作为getter/setter方法的功能,例如:

function Obj() { 
    var privateVar = 'xxx'; 

    return { 
     getPrivateVar: function() { 
      return privateVar; 
     }, 
     setPrivateVar: function (val) { 
      privateVar = val; 
     } 
    }; 
} 

这样,你就必须从构造函数外部访问的变量,但你将无法修改它而不用调用适当的函数(setter)。

使用原型是一个广泛的话题。它允许您节省内存(方法在对象实例之间共享,而不是在每次创建新对象时创建),它允许您通过修改原型来修改对象的所有实例中的方法。而且原型可以用来模仿继承(寻找“原型链”)。

我推荐阅读"JavaScript: The Good Parts"