在Object.create()中定义函数

时间:2012-12-05 03:16:01

标签: javascript design-patterns

我想使用Object.create函数创建一个对象(没有任何原型,第一个参数为null )。

我在某处读到属性确定JavaScript中对象的状态,JavaScript有三种不同的属性:

  • 命名数据属性
  • 命名的访问者属性
  • 内部属性

因此,当我在对象中定义一个函数时,我是否应该始终将其定义为named accessor property

var obj = Object.create(null, {   
     a:{
        get:function(){
           alert('jQuery nyan!');          
        }
     }
});​

或者我应该将该函数定义为named data property,当它既不是setter也不是getter时? [例如,一些改变DOM obj的jQuery函数]

var obj = Object.create(null, {
     a:{
        value:function(){
              alert('jQuery nyan!');          
        }
     }
});​

我应该采取哪种方法?在性能(速度)和内存管理方面,它们有区别吗?它们似乎都没有任何例外。

obj.a;
//output: 'jQuery nyan!'

2 个答案:

答案 0 :(得分:1)

为了更容易引用它们,让我们按如下方式定义它们

var objA = Object.create(null, {a: {get:  function(){alert('jQuery nyan!');}}});
var objB = Object.create(null, {a: {value:function(){alert('jQuery nyan!');}}});

现在,objA.aobjB.a()的调用几乎没有区别,除了使用()

然而,存在一些差异。 主要区别在于您无法将参数传递给getter,而是按原样调用它。这意味着objA.a(1,2,3)不会使用arugments 1, 2, 3调用该函数。实际上,在调用之后会抛出错误,假设getter没有返回 Function (你有效地尝试undefined(1,2,3))。

第二个区别要求我们记住Object.create的第二个参数需要descriptors的对象,其中包含标记writable(默认为 false )。这里的不同之处在于您无法在writable:true上设置objA.a,因为“属性不能同时具有访问权限且可写或具有值”。这意味着如果您希望更改getter的方法,则必须重新定义属性,而对于 value ,您可以启用=来更改与该属性关联的方法

此外,没有setter objA.a = <expr>根本不会执行任何操作。

通常情况下,您只在以下情况下使用getter和setter,否则将value作为标准行为;

  • 轻量级计算输出
  • 验证输入(以保护对象)
  • 隐藏直接访问变量
  • 保持变量或属性名称可能更改的标准API

答案 1 :(得分:1)

如果您不关心兼容性,使用gettersetters可能是替换setNAME()getNAME()的好方法。还有no significant performance gain/loss comparing to function version

请注意,因为它看起来像访问变量而不是调用函数,所以getter/setter函数应该非常轻,以满足这种期望。

并且不要像jQuery那样对getter和setter使用一个函数,它只是非常慢。由于javascript中没有函数签名,因此使用if/else进行模拟将导致大量性能损失。