是否有可能使Javascript函数表现得好像它是一个字符串,没有()

时间:2013-05-09 22:40:00

标签: javascript string function

这可能还是我在这里咆哮错误的树?

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

3 个答案:

答案 0 :(得分:9)

您似乎在谈论 getter 方法。如果这就是你的意思,你可以使用它:

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

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

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

答案 1 :(得分:4)

bfavaretto's解决方案的替代方法是使用对象的文字语法。与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以便可以重新计算总和。或者你可以使用setter。

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);

答案 2 :(得分: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