0

我是一个相对有经验的 c#(在那个 c++ Win32 之前)开发人员,我是 javascript 新手,并且对this指针有疑问。

我正在使用 knockout.js,一个名为 subscribe 的函数接受一个this变量,该变量将在回调函数中设置。

根据我从 Win32 天和 C# 开始的思考方式,在任何回调函数上,我都想要一个包含我的状态的范围对象。

在这种情况下,我使用了thisjavascript 来设置我的回调范围。

我的问题是:

  1. 现在一切正常(如果您有兴趣,请在此处使用完整的小提琴),但是我做了什么可怕的事情吗?

  2. 是否有任何理由this使用而不是将显式范围变量作为参数传递(这对我来说会让事情更容易理解,这使得工作有点隐藏)。

  3. 预期用途是this什么?

http://knockoutjs.com/documentation/observables.html它说:

subscribe 函数接受三个参数:callback 是通知发生时调用的函数,target(可选)定义回调函数中 this 的值,event(可选;默认为“change”)是事件的名称接收通知。下面的例子

myViewModel.personName.subscribe(function(oldValue) {
    alert("The person's previous name is " + oldValue);
}, null, "beforeChange");

我的代码片段如下:

var computedOptions = createComputedDepdency(viewModel[option.requires.target],option.data);
viewModel[option.optionsName] = computedOptions;

console.log("making callback scope object for: " + option.optionsName );
var callbackScope = {
    callbackName: option.optionsName,
    options: computedOptions,
    selectedValue: viewModel[option.selectedName]
};

// when the list of available options changes, set the selected property to the first option
computedOptions.subscribe(function () {
    var scope = this;
    console.log("my object: %o", scope);   
    scope.selectedValue(scope.options()[0].sku);
    console.log("in subscribe function for..." + scope.callbackName);
},callbackScope);
4

3 回答 3

1

在 javascript 中,“this”是指调用您的函数的对象。只有在您使用“new”关键字的情况下,您才能期望它指向当前对象(函数)。

var MyObject = function () {
  this.hello = function () { console.log(this); }
}

var instance = new MyObject();

有一种方法可以确保这始终是您所期望的,那就是创建一个变量来为您存储正确的引用并使用它而不是这个......在你的例子中它会类似于这个......

computedOptions = function () {
  var that = this;
}

computedOptions.subscribe(function () {
    console.log("my object: %o", scope);   
    scope.selectedValue(that.options()[0].sku);
    console.log("in subscribe function for..." + that.callbackName);
},callbackScope);

MDN JavaScript 参考不可避免地会比我自己解释得更好,看看吧。

于 2013-10-19T18:53:07.367 回答
1

首先是语义注释:

this函数的作用域与单词无关。与context相关this。范围与另一个函数内的变量和函数的可访问性有关。

当您尝试在声明它的函数之外读取变量时,您会尝试访问其范围之外的 var。所以你不能这样做,因为 var 在当前位置无法访问的范围内。

现在一切正常(如果您有兴趣,请在此处进行操作),但是我做了什么可怕的事情吗?

如果它有效,那就没那么可怕了:-)

是否有任何理由使用它而不是将显式范围变量作为参数传递(这会让事情更容易理解,这使得工作有点隐藏)。

快速阅读:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

在 javascript 中, 的值this取决于函数的调用方式。

在某种程度上,这种方法可以节省令人讨厌的上下文段落作为参数:在一个有据可查的库中,this使用非常直观。在其他情况下,我同意当您在没有严格逻辑的情况下不断更改应用程序中的上下文时,可能会感到困惑。

这样做的预期用途是什么?

我们应该永远记住 javascript 是如何以及何时诞生的。它是为浏览器而生的,目的是为了与 DOM 交互。

为此,上下文可以感知基于哪个元素调用函数的变化。

例如:

var divs = document.getElementsByTagName('DIV');

for(var i = 0; i < divs.length; i++) {
    divs[i].addEventListener('click',_clickHandler);
}

function _clickHandler() {
    this.innerHTML = "clicked";
}

演示http://jsfiddle.net/AYBsL/1/

这是一个示例,说明在 javascript 中隐式更改上下文是如何有用的。

您也可以对用户定义的函数执行此操作:调用函数时可以更改上下文:

_clickHandler.call(divs[0]); // simulate click of first div
于 2013-10-19T20:19:31.850 回答
0

你不应该混合范围和this. this应该模仿 java 或 ++ 等经典 oop 语言,即保留对实例对象的引用。但它可以用于在给定的上下文中使用.apply()or执行任意函数.call

那么作用域呢,你不需要做任何事情来将作用域传递给函数,因为外部作用域可以在函数内部自动访问。你应该阅读关于闭包的内容——它是 javascript 中最好的部分。

于 2013-10-19T18:51:13.737 回答