Возможно ли, что функция JavasScript действует так, как если бы она была строкой, no()

Возможно ли это, или я лаяю неправильное дерево здесь?

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 not what I would like to know.

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

Update:

Объект, который должен представлять fnc, на самом деле является документом сариссы 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

Ответ 1

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

Ответ 2

Вы, кажется, говорите о методе геттера. Если это вы имеете в виду, вы можете использовать это:

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 для получения глобальной переменной. Обычно вы используете это, чтобы получить значение частной переменной в вашем экземпляре объекта, и в этом случае вы можете изменить его только с помощью соответствующего устройства.

Ответ 3

Альтернативой решению 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);