为什么javascript函数知道这个实例

时间:2013-04-08 16:33:41

标签: javascript

如何在addChangedValue函数中的sampleViewModel实例未定义或为null?

从实例化的范围来看,我不能在addChangedValue函数中知道sampleViewModel。

$(function(){

    var PersonViewModel = function() {
        var me = this;
        me.firstName = ko.observable('Lisa'),
        me.lastName = ko.observable('T'),
        me.changes = ko.observableArray()
    };

    var sampleViewModel = new PersonViewModel();

    sampleViewModel.firstName.subscribe(function(newValue) {
        addChangedValue("firstname refreshed: " + newValue);
    });

    function addChangedValue(updatedValue) {
        sampleViewModel.changes.push({ value: updatedValue });
    };

    ko.applyBindings(sampleViewModel, document.getElementById('data'));
});

3 个答案:

答案 0 :(得分:2)

肯定会的。闭包在词法上与它们被定义的范围绑定,因此闭包也已定义的范围中定义的任何内容都将为该闭包所知。

此外,addChangedValue可以访问其封闭范围中的任何变量,除非通过在该函数中定义一个类似命名的变量来隐藏它。

答案 1 :(得分:1)

作为addChangedValue的参数的匿名函数形成一个闭包。 sampleViewModel是函数中与在封闭范围内相同的变量。闭包是函数(通常是匿名的,如在您的情况下)与上下文的组合。声明函数时范围内的所有变量在该函数中都可用。您可以阅读有关闭包here

答案 2 :(得分:0)

是的,你已经创建了一个Closure。例如:

function init() {
    var person = { name: 'Joe' };

    var callMeLater = function() {
        alert(person.name);
    };

    return callMeLater;
};

var fn = init();
fn(); // alerts 'Joe'

在此示例中,init()函数有自己的范围 - 这对您来说似乎并不陌生。因此,例如person在其中声明,因此在init()本地。 callMeLater在此函数中定义,创建一个Closure。封闭函数(init)本地的所有变量也可用于callMeLater。这就是为什么本例中的最后一行警告Joe,而您的示例使sampleViewModel可用。

就像在Java中你做到了这样:

public class Person {
    public string name;

    public Person(string name) {
        this.name = name;
    }

    public MyClosure getClosure() {
        string someOtherThing = "other";
        return new MyClosure(this, someOtherThing);
    }
}

public class MyClosure {
    public Person person;
    public string someOtherThing;

    public MyClosure(Person person, string someOtherThing) {
        this.person = person;
        this.someOtherThing = someOtherThing;
    }

    public void callMeLater() {
        log(person.name);
    }
}

var person = new Person("Joe");
var closure = person.getClosure();
closure.callMeLater(); // Logs "Joe"

您可以将MyClosure类视为通过在函数内定义函数为您创建的隐式包装器。