簡體   English   中英

Javascript:始終在執行上下文中執行函數

[英]Javascript: always execute function in execution context

我寫了這個快速模板函數:

var templatize = function(string) {
    return function (string) {
      return string.replace(/{{(.*?)}}/g, function(pattern, match) {
        value = this[match];
        if (value) {
          return value;
        } else {
          return pattern;
        }
      });
    }.call(this, string);
}

這樣做:

var foo = "bar", bar = "foo";
templatize("We are {{foo}} and {{bar}}, but not {{crazy}}"); // "We are bar and foo but not {{crazy}}"

我對此感到很滿意,除了遇到范圍問題。 當然,可以通過namedscope訪問templatize方法,但是,在我的函數中無法自動訪問templatize的當前執行上下文。

像調用$.proxy(templatize, this)("We are {{foo}} and {{bar}}, but not {{crazy}}")應該起作用,對嗎?

但是我想實現這一目標,而無需調用$ .proxy()(最好沒有任何jQuery),以便上下文自動轉移到執行代碼中。

我掙扎.call() .apply()和其他關閉,但我想我在這是有可能的互聯網讀的地方。 謝謝

您可以避免使用jQuery來做到這一點:

var templatize = function(string) {
    var me = this; // the data source
    return string.replace(/{{(.*?)}}/g, function (full, key) {
        // "this" refers to the string itself
        return me[key] || full;
    });
}

如果要使用jQuery.proxy() ,請包裝替換函數:

var templatize = function(string) {
    return string.replace(/{{(.*?)}}/g, jQuery.proxy(function (full, key) {
        // "this" now refers permanently to the data source
        return this[key] || full;
    }, this));
}

在這兩種情況下,都可以使用call將數據源綁定this

templatize.call({ hello: 'Hi!' }, '{{hello}}');

更進一步

您可以通過編譯模板以進行重用來進行優化:

function compile(tpl) {
    var i = -1, tmp = [];
    tpl = tpl.split(/{{([^{}]+)}}/);
    while (++i < tpl.length) {
        if (i % 2) tmp.push('this["' + tpl[i] + '"]');
        else if (tpl[i]) tmp.push('"' + tpl[i].replace(/"/g, '\\"') + '"');
    }
    return new Function(
        'return [' + tmp.join() + '].join("");'
    );
}

用法示例:

var tpl = compile('{{hello}} {{hello}}');
tpl.call({ hello: 'Hi!' }); // "Hi! Hi!"
tpl.call({ hello: 'Yo!' }); // "Yo! Yo!"

對於上面的示例,這是compile返回的函數:

function () {
    return [this["hello"]," ",this["hello"]].join("");
}

請注意,您也可以使用數組:

var tpl = compile('{{1}} {{0}}');
tpl.call(['a', 'b']); // "b a"

性能測試: http : //jsperf.com/template-compiling

為什么不傳遞包含視圖變量的對象? 會更清潔,然后可能在視圖中顯示任何現有變量。

var templatize = function(string, variables) {
  return function (string) {
    return string.replace(/{{(.*?)}}/g, function(pattern, match) {
      value = variables[match];
      if (value) {
        return value;
      } else {
        return pattern;
      }
    });
  }.call(this, string);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM