目前有一个问题困扰着我。我有一个如下定义的 Durandal View 模型,但是当我逐步执行代码时,this
的值以及其他变量和函数在各处都会发生变化。
我对下面的内容进行了评论,因为在代码中移动时更容易显示各种值。
define(['durandal/plugins/router'], function (router) {
var _outerRouter = router;
var _outerSelf = this;
var viewModel = function () {
var _self = this;
var _router = router;
var _searchCriteria = ko.observable('');
var _searchResults = ko.observableArray([]);
var _messages = ko.observableArray([]);
this.searchCriteria = _searchCriteria;
this.searchResults = _searchResults;
this.messages = _messages;
this.search = function () {
//
// When called from the view bindings:
// > this = viewModel
// > _self = _outerSelf = _outerRouter = undefined
// > _router = defined
//
var that = this;
//
// N.B. I set callback context to the viewModel
//
var req = $.ajax({
url: '../api/v1/things',
dataType: 'json',
context: this,
data: {
searchCriteria: this.searchCriteria()
}
})
.done(function (results, status, request) {
//
// When called back:
// > this = viewModel
// > _self = _outerSelf = _outerRouter = undefined
// > _router = defined
//
this.searchResults.removeAll();
this.messages.removeAll();
//
// Now when calling:
// > doShowResult = showResult = undefined
// > this.showResult = defined (have to use 'this')
// > displayMultipleResults = defined
//
if (results.length == 1) {
this.showResult(results[0]);
}
else {
displayMultipleResults(results);
}
});
function displayMultipleResults(results) {
//
// When called from ajax.done():
// > this = Window ?!?!
// > that = viewModel
// > _self = _outerSelf = _outerRouter = undefined
// > _router = defined
//
that.messages.push({ title: 'Found Lots of Things', body: "Please select...blah blah blah", type: 'info' });
for (var i = 0; i < results.length; i++)
that.searchResults.push(results[i]);
};
};
function doShowResult(result) {
//
// When called from ajax.done():
// > this = viewModel
// > _self = _outerSelf = _outerRouter = undefined
// > _router = defined
//
// and then
//
// When called from the view bindings:
// > this = the bound searchResult object
// > _self = _outerSelf = _outerRouter = undefined
// > _router = defined
//
_router.navigateTo('show-my-thing');
}
this.showResult = doShowResult;
};
return viewModel;
});
这是它所绑定(bind)的 View :
<div>
<div class="container-narrow">
<div class="row-fluid">
<div class="span12">
<h3>Search</h3>
<p>Enter search criteria...</p>
<div class="control-group">
<input type="text" class="input-block-level" placeholder="Criteria" data-bind="value: searchCriteria"/>
</div>
<div class="pull-right">
<button class="btn btn-primary" data-bind="click: search">
<i class="icon-search icon-white"></i> Search
</button>
</div>
</div>
</div>
<br />
<!-- ko foreach: messages -->
<div class="row-fluid">
<div class="alert" data-bind="css: { 'alert-error': type == 'error', 'alert-info': type == 'info', 'alert-success': type == 'success' }">
<strong data-bind="text: title"></strong> <span data-bind="text: body"></span>
</div>
</div>
<!-- /ko -->
<!-- ko foreach: searchResults -->
<div class="row-fluid">
<div class="span12 well well-small">
<div class="span10 search-result">
<label>Resut:</label> <span data-bind="{text: $data}"></span><br />
</div>
<div class="span2">
<button class="btn btn-mini btn-success pull-right" data-bind="click: $parent.showResult">
View
</button>
</div>
</div>
</div>
<!-- /ko -->
</div>
</div>
我的主要问题是:
为什么我可以在任何地方访问
_router
但不能访问_self
(或任何其他变量(_searchCriteria 等))?当在
ajax.done()
内执行并且this
的值等于 viewModel 但在它进入 displaySearchResultthis
等于 Window 对象?当在
ajax.done()
内时,doShowResult
和showResult
是undefined
但this.showResult
工作正常,如果this
是viewModel
那么showResult
就被定义了吗?幸运的是,在这种情况下,我只需要在
doShowResult
中导航,并且当我从ajax.done
调用时定义_router
> 并从 View 绑定(bind)。但是,如果我需要从 View 模型访问一个值怎么办 - 如果从 View 绑定(bind)调用,这将不可用 - 我如何更改绑定(bind)或代码来支持它(最好以非黑客方式)?
预先感谢任何人都可以对此提供任何帮助。
最佳答案
“this”关键字在 JavaScript 中的行为与其他语言非常不同,可见范围的概念也是如此。
任何给定时间“this”的值取决于您从中访问它的函数的调用上下文。有四种不同的方法来调用方法,每种方法对“this”都有不同的含义。
作为函数调用(调用命名函数):this = window(即全局对象)。
function fName() { }; fName(); // this = window
作为方法调用(调用对象的属性):this = 对象
var o = {}; o.whatever = function() {}; o.whatever(); // this = o
作为构造函数调用(使用 new 关键字):this = 新对象
var Animal = function() { }; // best practice to capitalise the initial letter of function intended to be called as constructor. var cat = new Animal(); // this = (what will become cat)
使用 apply() 和 call() 方法调用:(this = 第一个参数)
function fName() { }; var obj1 = {}; fName.apply(obj1); // this = obj1 fName.call(obj1); // this = obj1
关于javascript - 此值在 Durandal View 模型中的值(value),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16125160/