有没有可能;返回一个getter“;在javascript中

有没有可能;返回一个getter“;在javascript中,javascript,Javascript,我想这样做: function x(){ var o = {}; o.__defineGetter__('y', function(){ return new Date(); }); return o.y; } var z = x(); console.log(z); //Wait 1 second console.log(z); //Date should be one second past the last printing 当然,这不

我想这样做:

function x(){
    var o = {};
    o.__defineGetter__('y', function(){
        return new Date();
    });

    return o.y;
}

var z = x();
console.log(z);
//Wait 1 second
console.log(z); //Date should be one second past the last printing
当然,这不起作用,因为在返回o.y时会对其进行计算。我正在寻找一种返回作为getter的变量的方法。下面的例子给了我这样的希望:

function x(context){
    //Bind the getter to the passed in scope
    context.__defineGetter__('y', function(){
        return new Date();
    });
}

x(this);
console.log(y);
//Wait 1 second
console.log(y); //Date is one second past last printing
有人试过这样做吗

是的,我熟悉使用不同语法对类似行为建模的其他方法。我只想让这种特殊的语法适用于特殊的场景

谢谢


Chris

这里的问题是,当您在第一个函数中返回
o.y
时,您没有返回getter方法,而是返回通过调用getter方法返回的日期对象。然后将该日期对象分配给
z
,因此每次
console.log(z)
,都记录该日期对象,而不是再次调用该函数

在第二个示例中,当您使用console.log(y)时,实际上每次都在调用该函数

一个可能的解决方案,虽然可能不是您想要做的,是让第一个示例中的getter返回一个函数。那就行了

function x(){
    var o = {};
    o.__defineGetter__('y', function(){
        return function() {
            return new Date();
        }
    });

    return o.y;
}

var z = x();

console.log(z());
//Wait 1 second

setTimeout( function() {
    console.log(z()); //Date is one second past last printing
}, 1000)

Getter方法在Javascript中是一种特殊情况,因为它们调用函数时最后没有使用通常的
()
,我想这可能会让人困惑,因为通常情况下,您希望
o.y
返回函数而不是调用函数。

答案是否定的,当像变量一样访问变量时,不能将值赋给变量,从而使该变量的行为类似于函数。正如您在问题中指出的,最接近的方法是使用getter函数定义属性。您不能创建如您所描述的那样工作的函数的局部变量

function x(n) { 
    Object.defineProperty(this, n, { 
        get: function() { 
            return new Date(); 
        }
    }); 
}

x('y')
但是,您可以定义一个函数,该函数使用getter函数(或者更确切地说,是全局对象上的属性)定义一个全局属性,并使其看起来像您所做的那样。对于exmaple,在ES5中,以下内容将创建一个全局变量
y
,其作用如您所述

function x(n) { 
    Object.defineProperty(this, n, { 
        get: function() { 
            return new Date(); 
        }
    }); 
}

x('y')
注意,这仅在非严格模式下有效。在严格模式下,
的值为
未定义


我无法理解为什么你会希望一个变量像这样运行。

对于被否决的人:如果你要这样做,请给出一个解释。如果你注意到有什么错误,留下一条评论会更有帮助。你的
函数x…。
教的是糟糕的编码风格,应该用
var z=function(){return new Date()}替换它。这是原始海报上的代码,不是我的。我抄了他写的东西,改了几行。在投票否决之前请注意。我没有投票否决你,但你不应该让这个问题掩盖了答案。正如bennedich所指出的,有一种更简单的方法来定义这样一个函数。我不同意,bennedich不必要地在全局范围中添加了一个变量,而我的示例将其封装在一个函数中。@nikc.org谢谢!但现在它的格式很好,有人可能会尝试使用它。哎呀!你可以。试着这样做。var x={valueOf:function(){console.log(“我应该是一个变量”);返回Math.random()};控制台日志(10*x);这是非常聪明和该死的接近。但是,它不适用于给定的情况,即“console.log(x);”打印“[object object]”,因为将x作为参数传递不会强制调用valueOf()。但还是有点酷!这应该是公认的答案。但是,从函数x()返回一个带有“valueOf”属性的对象会更简单,例如“function x(){return{valueOf:function(){…};}”是的,我可以用更多更简单的方式编写。但是我想x()和其中的对象定义的原因是o可以有更多的方法和属性,它们都是在x的私有上下文中定义的。x()只返回o,在打印时显示时间(在该示例中),但也可以使用o.speak()或类似的内容。因此,就问题而言,答案应该尊重上下文,即使不完整、看似无用或错误。但我的意思是,没有理由使用函数作为对象来返回和依赖具有不完整浏览器支持的proto。原来的问题没有返回函数对象,所以我认为这只是增加了不必要的干扰。这是一个非常聪明的解决方案,解决了我给出的示例。我完全忘了我想做什么,但它解决了。因此,这确实是一件非常特殊/奇怪的事情,但在该模块的上下文中,它有一个特定的目的。由于valueOf的使用,此解决方案无法解决我的总体需求,但我将为您回答我实际提出的问题提供分数:)
function x(){
    var o = function() {};
    o.__proto__ = {
           valueOf:  function() { 
               return new Date().toString(); 
           }
     };

    return o;
}

var z = x(); 
console.log(z);  // Tue Mar 13 2012 14:10:10 GMT+0200 (GTB Standard Time)
setTimeout(function() { 
   console.log(z); // Tue Mar 13 2012 14:10:12 GMT+0200 (GTB Standard Time)
}, 2000);