虽然我特意使用KnockoutJS来解决这个问题,但我的问题更像是一般的javascript问题。
然而,很好理解ko.observable()和ko.observableArray()返回一个方法,因此在为它们赋值时,需要将目标作为方法调用,而不是简单地为它们赋值。我正在使用的代码也应该支持普通对象和数组,这就是为什么我需要解析一个方法来调用为目标赋值。
想想这两个例子:
非工作方式(此方法在调用方法中更改):
// Assigning value to the target object
var target;
// target can be of any of thr following types
target = ko.observableArray(); // knockout observable array (function)
// target = ko.observable(); // knockout observable (function)
// target = {}; // generic object
// target = []; // generic array
//#region resolve method to call
var method;
if (isObservable(target)) {
// if it is a knockout observable array, we need to call the target's push method
// if it is a konckout observable, we need to call the target as a method
method = target.push || target;
} else {
// if target is a generic array, we need to use the array's push prototype
// if target is a generic object, we need to wrap a function to assign the value
method = target.push || function(item){ target = item; };
}
//#endregion
// call resolved method
method(entity);
工作一个(这个背景很好):
if (isObservable(target)) {
if (target.push) {
target.push(entity);
} else {
target(entity);
};
} else {
if (target.push) {
target.push(entity);
} else {
target = entity;
};
}
现在,对于实际问题:
在第一种方法中,稍后在执行链中,当使用knockout observable knockout时,引用其自身内的this
上下文,尝试访问observable本身(即如果有人想知道,则为this.t())。在这种特殊情况下,由于callin的方式,this
已更改为window
对象,而不是指向原始的可观察对象。
在后一种情况下,淘汰赛的this
背景正常。
你们中的任何一个javascript大师都可以告诉我,我的调用方式是如何改变被调用函数的“this”上下文的?
好的,我知道有人想要小提琴,所以这里有:)
Method 1 (Uncaught TypeError: Object [object global] has no method 'peek')
P.S。我不是要修复代码,我试图理解为什么我的代码会更改this
上下文。
更新
感谢您的快速解答!当我不知道为什么(尤其是如何)发生了什么事情时,我必须说我讨厌它。从你的答案I fiddled up this quick fiddle来重新调整情况,我想我现在得到了它:)
// So having an object like Foo
function Foo() {
this.dirThis = function () {
console.dir(this);
};
};
// Instantiating a new Foo
var foo = new Foo();
// Foo.dirThis() has it's original context
foo.dirThis(); // First log in console (Foo)
// The calling code is in Window context
console.dir(this); // Second log in console (Window)
// Passing a reference to the target function from another context
// changes the target function's context
var anotherFoo = foo.dirThis;
// So, when being called through anotherFoo,
// Window object gets logged
// instead of Foo's original context
anotherFoo(); // 3rd log
// So, to elaborate, if I create a type AnotherFoo
function AnotherFoo(dirThis){
this.dirThis = dirThis;
}
// And and instantiate it
var newFoo = new AnotherFoo(foo.dirThis);
newFoo.dirThis(); // Should dir AnotherFoo (4th in log)
答案 0 :(得分:3)
如果您正在选择将在通话时使用的“此”, 你应该使用bind,这就是为此完成的。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
因此,如果SomeObject有一个push方法,那么像这样存储它将不起作用:
var thePushMethod = someObject.push;
因为在写这个时你松开了函数的上下文。
现在,如果你这样做:
var thePushMethod = someObject.push.bind(someObject);
上下文现在存储在thePushMethod中,您只需使用
调用 thePushMethod();
请注意,您也可以绑定参数,例如,您可以编写:
var pushOneLater = someObject.push.bind(someObject, 1 );
// then, later :
pushOneLater(); // will push one into someObject
答案 1 :(得分:1)
考虑这个例子,
function Person () {
this.fname = "Welcome";
this.myFunc = function() {
return this.fname;
}
};
var a = new Person();
console.log(a.myFunc());
var b = a.myFunc;
console.log(b());
<强>输出强>
Welcome
undefined
当您拨打a.myFunc()
时,当前对象(this
)设置为a
。所以,第一个例子工作正常。
但在第二种情况下,var b = a.myFunc;
只获得对函数的引用,当您调用它时,您不会调用任何特定对象,因此会分配窗口对象。这就是它打印undefined
的原因。
要解决此问题,您可以使用this
函数显式传递call
参数,如下所示
console.log(b.call(a));
因此,对于您的情况,您可能必须这样做
method.call(target, entity);