1

addChangedValue 函数中的 sampleViewModel 实例怎么可能不是 undefined 或 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'));
});
4

3 回答 3

2

它肯定会。闭包在词法上绑定到定义它们的作用域,因此在作用域中定义的任何内容(也定义了闭包)都将被该闭包所知。

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

于 2013-04-08T16:36:42.497 回答
1

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

于 2013-04-08T16:36:11.523 回答
0

是的,你已经创建了一个闭包。举例:

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

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

    return callMeLater;
};

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

在这个例子中,init()函数有它自己的作用域——这对你来说似乎并不新鲜。因此,例如 person 被声明在其中,因此是init(). callMeLater在这个函数内部定义,创建一个闭包。封闭函数 ( 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 类视为通过在函数内部定义函数而为您创建的隐式包装器。

于 2013-04-08T19:29:56.067 回答