javascript - 此值在 Durandal View 模型中的值(value)

标签 javascript knockout.js requirejs durandal

目前有一个问题困扰着我。我有一个如下定义的 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>

我的主要问题是:

  1. 为什么我可以在任何地方访问 _router 但不能访问 _self(或任何其他变量(_searchCriteria 等))?

  2. 当在 ajax.done() 内执行并且 this 的值等于 viewModel 但在它进入 displaySearchResult this 等于 Window 对象?

  3. 当在 ajax.done() 内时,doShowResultshowResultundefined this.showResult 工作正常,如果 thisviewModel 那么 showResult 就被定义了吗?

  4. 幸运的是,在这种情况下,我只需要在 doShowResult 中导航,并且当我从 ajax.done 调用时定义 _router > 并从 View 绑定(bind)。但是,如果我需要从 View 模型访问一个值怎么办 - 如果从 View 绑定(bind)调用,这将不可用 - 我如何更改绑定(bind)或代码来支持它(最好以非黑客方式)?

预先感谢任何人都可以对此提供任何帮助。

最佳答案

“this”关键字在 JavaScript 中的行为与其他语言非常不同,可见范围的概念也是如此。

任何给定时间“this”的值取决于您从中访问它的函数的调用上下文。有四种不同的方法来调用方法,每种方法对“this”都有不同的含义。

  1. 作为函数调用(调用命名函数):this = window(即全局对象)。

    function fName() { };
    fName(); // this = window
    
  2. 作为方法调用(调用对象的属性):this = 对象

    var o = {};
    o.whatever = function() {};
    o.whatever(); // this = o
    
  3. 作为构造函数调用(使用 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)
    
  4. 使用 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/

相关文章:

javascript - 如何解决 Handlebars.js 缺少 noConflict 方法的问题?

javascript - 如何在我的 JavaScript 代码的 PhpStorm 中包含 "require"?

javascript - 如何使用 Node 的某些选项运行 webpack

javascript - 当我们使用 JavaScript 更改元素类时如何将其他样式设置为默认样式

javascript - 如何使用另一页面的 Knockout JS 将一个 viewModel 数据传递到其他 ViewModel 函数

c# - Asp.Net WebApi OWIN 身份验证

javascript - MS excel 类似 web ui 中的功能更复杂?

javascript - 如何将模型对象获取到 Javascript 变量

javascript - 查找从一个集合到另一个集合的重复对象 - 在knockout JS中使用2个数组

javascript - yeoman:使用 yo webapp,然后将 backbone 和 backbone.layoutmanager 添加到组合中