将新的变量范围应用于对象

时间:2018-03-10 02:29:39

标签: javascript scope

以下脚本允许jQueryUI的自动完成功能与xeditable一起使用,并且可以按照需要运行:

$(function(){
    dialog.find('a.car').xEdit('autocomplete',{name:'carName', title:'Car Name', url: '/1.0/cars/', pk: carId, autocomplete: {
        url: "/1.0/cars/",
        params: {term:null, fields:['id','name']}
    }});
});

$.fn.xEdit = function(type, options) {
    var common={
        placement: 'right',
        ajaxOptions: {type: "PUT"},
        send: 'always'
        // pk: null, title: null, params: {name: null}, url: null, //Must be passed
    }
    // Not shown, but different actions will be performed based on "type"
    options.params={name: options.name};
    delete(options.name);
    options.type='text';
    //autocomplete is not used by xeditable but by jQueryUI autocomplete, but doesn't seem to hurt anything
    this.editable($.extend({}, common, {value: null}, options))
    .on('shown', function(e, editable) {
        //console.log('on.show','this',this,'e',e,'editable',editable)
        var elem=this;
        var $input=editable.input.$input.val('');
        var $button=$input.parent().next().find('button.editable-submit').css('opacity', 0.3)
        .bind('click.prevent', function() {return false;});
        var autocomplete={
            source: function( request, response ) {
                options.autocomplete.params.term=request.term;
                $.getJSON( options.autocomplete.url, options.autocomplete.params, function(json) {
                    var data=[];
                    for (var j = 0; j < json.length; j++) {
                        data.push({id:json[j].id,label:json[j].name});
                    }
                    response(data);
                } );
            },
            minLength: 2,
            position: { my : "left top+20", at: "left bottom" },
            select: function(e, ui) {
                $input.blur();
                $button.css('opacity', 1).unbind('click.prevent');
                editable.option('params', {
                    value: ui.item.id,
                    name: options.params.name
                });
            }
        };
        if (typeof options.autocomplete.select != "undefined") autocomplete.select=options.autocomplete.select;
        $input.focus(function() {
            $button.css('opacity', 0.3).bind('click.prevent', function() {return false;});
        })
        .autocomplete(autocomplete)
        .autocomplete('widget').click(function() {return false;});
    });
    break;
};

我现在希望能够使用select: function(e, ui) {...}中定义的新函数覆盖xedit中的options(以及后来的其他方法),并尝试以下方法:

$(function(){
    dialog.find('a.car').xEdit('autocomplete',{name:'carName', title:'Car Name', url: '/1.0/cars/', pk: carId, autocomplete: {
        url: "/1.0/cars/",
        params: {term:null, fields:['id','name']},
        select: function(e, ui) {
            //Be able to do something different
            $input.blur();
            $button.css('opacity', 1).unbind('click.prevent');
            editable.option('params', {
                value: ui.item.id,
                name: options.params.name,
                model: 123
                }
            );
        }
    }});
});

但它会导致错误,指出eui$input$buttoneditableoptions都未定义。我认为这是由于在不同的变量范围内定义新函数。

如何在一个变量范围内定义一个对象,然后对其应用另一个范围?

PS。我希望我这样做是非常难看的,如果有更漂亮的方式,请随时发表评论。

1 个答案:

答案 0 :(得分:1)

好吧,我之前从未使用过这个xEdit插件,但你的问题与JavaScript有关,所以我可以给我两分钱。

在第一个示例中,select处理程序可以访问这些变量,因为它在词法上绑定到外部函数的范围(shown事件的处理程序)。在另一个函数中声明函数时,此构造称为闭包。内部函数,即使在其容器函数之外调用,也将始终记住其原始上下文。 这个链接是牢不可破的。

function a() {
  const favoriteSport = 'Football';
  const team = 'Packers';

  return function(){
    console.log(`My favorite sport and team are "${favoriteSport}" and "${team}" respectively`);
  };
}

const b = a();
const c = b;
const d = c;
const e = d;

const anObject = { e };
// One does not simply forget its origins... =)
anObject.e(); //=> My favorite sport and team are "Football" and "Packers" respectively

// This is what you're doing...
anObject.e = function(){
  console.log(`I really do love "${favoriteSport}" and the "${team}".`);
};
// BOOOM!
anObject.e(); //=> Uncaught ReferenceError: favoriteSport is not defined

当您在词汇上声明函数a的函数b 时,a无法访问b内声明的任何变量}。 这就是你要做的事情。

因此,在声明函数后,无法更改函数的范围。

Here's a fabulous SO question有很多关于闭包如何工作的好答案。