如何在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'));
});
答案 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类视为通过在函数内定义函数为您创建的隐式包装器。