10

这是可能的还是我在这里吠错了树?

var data = 'one';
function fnc(){
    this.out = function(){
        return data;
    }
}
var instance = new fnc();

alert(instance.out);
data = 'two';
alert(instance.out);

// I know that this would achieve that, but that's not what I would like to know.

alert(instance.out());
data = 'two';
alert(instance.out());

更新:

fnc 应该表示的对象实际上是一个 Sarissa dom 文档。这是 fnc() 的更详细版本,dom_doc()。下面接受的答案已集成到下面的函数中。

function get_doc(dom_node) {
    var doc;
    if (navigator.userAgent.indexOf("MSIE") >= 0) {
        doc = new ActiveXObject("Msxml2.DOMDocument.3.0");
        doc.loadXML(document.getElementById(dom_node).text);
    }
    else {
        doc = Sarissa.getDomDocument();
        doc = (new DOMParser()).parseFromString(document.getElementById(dom_node).textContent, "text/xml");
        // runs XSLTProcessor in modern browsers as if it was trasformNode
        doc.transformNode = function (stylesheet) {
            var processor = new XSLTProcessor();
            processor.importStylesheet(stylesheet);
            return new XMLSerializer().serializeToString(processor.transformToDocument(this));
        }

        // allows modern browsers to extract xml the way the legacy IEs did
        var getXML = {};
        getXML.toString = function(){
            return new XMLSerializer().serializeToString(doc);
        };
        doc.xml = getXML;
    }
    return doc;
}

演示: JSFIDDLE

4

3 回答 3

9

您似乎在谈论一种吸气剂方法。如果这就是你的意思,你可以使用这个:

var data = 'one';
function fnc(){
    Object.defineProperty(this, 'out', {
        get : function(){ return data; }
    });
}
var instance = new fnc();

alert(instance.out);

http://jsfiddle.net/zztYd/1

这与旧版浏览器不兼容(请参阅本页底部的兼容性表)。

此外,使用 getter 获取全局变量有点奇怪。通常,您使用它来获取实例对象上私有变量的值,在这种情况下,您只能使用相应的 setter 对其进行修改。

于 2013-05-09T22:44:34.863 回答
4

bfavaretto解决方案的替代方法是使用对象的文字语法。具有与 几乎相同级别的支持Object.defineProperty()

此外,您应该Object.defineProperty只调用一次,而不是每次实例化。

我还将提供一个更现实的示例,即计算属性,而不仅仅是引用全局。

http://jsfiddle.net/mendesjuan/zztYd/3/

function Pair(a,b){
    this.a = a;
    this.b = b;
}

Pair.prototype = {
    get sum(){ 
        return this.a + this.b; 
    }
};

var pair = new Pair(1,2);
alert(pair.sum);
pair.a = 5;
alert(pair.sum);

这样做的好处是您可以将实现更改为存储而不是计算,并且您不必更改它的调用方式。

function Pair(a,b){
    this.a = a;
    this.b = b;
    this.sum = a + b;
}

Pair.prototype = {
    setA: function(a){ 
        this.a  = a;
        this.sum = this.a + this.b; 
    }
};

var pair = new Pair(1,2);
alert(pair.sum);
pair.setA(5);
alert(pair.sum);

请注意,您现在必须调用setA以便重新计算总和。或者你可以使用二传手。

function Pair(a,b){
    this.a = a;
    this.b = b;
    this.sum = a + b;
}

Pair.prototype = {
    set a(a) {
        this.a  = a;
        this.sum = this.a + this.b; 
    }
};

var pair = new Pair(1,2);
alert(pair.sum);
pair.a = 5;
alert(pair.sum);
于 2013-05-09T23:05:48.390 回答
3

jsFiddle Demo

不过,这些类型的变通办法确实绕过了约定。()简单地在你的函数上使用它不应该有太大的障碍。使用()是预期的、可读的、最佳实践和行业标准。

不知道为什么smartcaveman决定删除他的使用答案,toString但这是一种可行的方法,虽然有点骇人听闻。

var data = 'one';
function fnc(){
 var getData = {};
 getData.toString = function(){
   return data;
 };
 this.out = getData;
}

var instance = new fnc();

alert(instance.out);//one
data = 'two';
alert(instance.out);//two

var s = instance.out;
alert(s);//two
于 2013-05-09T23:10:42.667 回答