为什么在 jQuery 插件中使用 this 而不是 $(this) [英] Why this and not $(this) in jQuery plugins

查看:12
本文介绍了为什么在 jQuery 插件中使用 this 而不是 $(this)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

文档告诉我们:

假设我们要创建一个插件,在一组检索元素绿色.我们所要做的就是添加一个名为greenify 为 $.fn ,它将像任何其他 jQuery 一样可用对象方法.

Let's say we want to create a plugin that makes text within a set of retrieved elements green. All we have to do is add a function called greenify to $.fn and it will be available just like any other jQuery object method.

$.fn.greenify = function() {
    this.css( "color", "green" );
};


$( "a" ).greenify(); // Makes all the links green.

注意,要使用 .css(),另一种方法,我们使用 this,而不是 $(this).这是因为我们的 greenify 函数是同一个对象的一部分作为 .css().

我不明白最后一段.函数将什么传递给 this?为什么不用 $(this) 来引用 jQuery 对象?难道我们不使用 $(el).css() 在 jQuery 中正常设置 CSS 吗?那为什么不在插件中呢?

I don't understand that last paragraph. What does the function pass to this? Why not $(this) to refer to the jQuery object? Don't we use $(el).css() to normally set CSS in jQuery? Then why not within a plugin?

推荐答案

让我们尝试深入一点:

让我们尝试生成一个非常简化的版本库,例如 jQuery,并将其命名为 microM

let's try generate a very simplified version lib, like jQuery, and name it for example microM

(function(global) {
  //function analog jQuery
  var microM = function(context) { 
    return new microM.fn.init(context);
  }

  //init prototype
  microM.fn = microM.prototype = {
    version: '0.0.0.1',
    constructor: microM
  };

  //function for initialize context
  var init = microM.fn.init = function(context) {
    if (context instanceof microM) context = microM.extend([], context.context);

    this['context'] = [].concat(context);
    return this;
  };

  init.prototype = microM.fn;

  //add function extend to prototype and as static method
  microM.extend = microM.fn.extend = function() {
    if (arguments.length == 2) {
      var target = arguments[0],
        source = arguments[1];
    } else {
      var target = this,
        source = arguments[0];
    }
    for (var key in source) {
      target[key] = source[key];
    }

    return target;
  }

  //extend microM prototype with a few simple function
  microM.fn.extend({
    min: function() {
      return Math.min.apply(Math, this.context);
    },
    max: function() {
      return Math.max.apply(Math, this.context);
    },
    pow: function(exponent) {
      for (var i = 0, len = this.context.length; i < len; i++) {
        this.context[i] = Math.pow(this.context[i], exponent);
      }
      return this;
    },
    get: function() {
      return microM.extend([], this.context);
    },
    map: function(callback) {//a function that takes a callback
      var result = [];
      for (var i = 0, len = this.context.length; i < len; i++) {
        var callbackResult = callback.call(this.context[i], this.context[i], i);
        if (callbackResult instanceof microM) result = result.concat(callbackResult.get());
        else result = result.concat(callbackResult);
      }
      return microM(result);
    }
  });

  //looks a like jQuery :-)
  global.microM = microM;
})(window);

所以我们有一个看起来像 jQuery 的最简单的库.现在我们要为其添加插件",例如函数square.

So we have a simplest lib looks a like jQuery. Now we want add "plugin" to it, for example function square.

在 jQuery 中,我们将其添加到原型中,或者 fn 在我们的例子中与原型相同:

As in jQuery we add this to prototype, or fn that same as prototype in our case:

microM.fn.square = function() {
  return this.pow(2);
}

这里我们可以直接从 this 调用 pow,因为在这种情况下 this 是我们的 microM 实例,并且microM.prototype 中的所有功能都可以直接使用;

here we can call pow directly from this because in this case this instance of our microM, and all functions from microM.prototype is available directly;

但是当我们调用我们的 map 函数时,它在回调中接受一个回调 this 将是具体元素,例如 Number 原语,因为我们这样称呼它

But when we call our map function that takes a callback inside callback this will be concrete element, for example Number primitive, because we call it like

callback.call(this.context[i], this.context[i], i);

调用函数中的第一个参数- 是 thisArg.

可能下面的代码片段可以清楚我的混乱解释:-)

Possibly code snippet below can make clear my muddled explanation :-)

(function(global) {
  var microM = function(context) {
    return new microM.fn.init(context);
  }

  microM.fn = microM.prototype = {
    version: '0.0.0.1',
    constructor: microM
  };

  var init = microM.fn.init = function(context) {
    if (context instanceof microM) context = microM.extend([], context.context);

    this['context'] = [].concat(context);
    return this;
  };

  init.prototype = microM.fn;

  microM.extend = microM.fn.extend = function() {
    if (arguments.length == 2) {
      var target = arguments[0],
        source = arguments[1];
    } else {
      var target = this,
        source = arguments[0];
    }
    for (var key in source) {
      target[key] = source[key];
    }

    return target;
  }

  microM.fn.extend({
    min: function() {
      return Math.min.apply(Math, this.context);
    },
    max: function() {
      return Math.max.apply(Math, this.context);
    },
    pow: function(exponent) {
      for (var i = 0, len = this.context.length; i < len; i++) {
        this.context[i] = Math.pow(this.context[i], exponent);
      }
      return this;
    },
    get: function() {
      return microM.extend([], this.context);
    },
    map: function(callback) {
      var result = [];
      for (var i = 0, len = this.context.length; i < len; i++) {
        var callbackResult = callback.call(this.context[i], this.context[i], i);
        if (callbackResult instanceof microM) result = result.concat(callbackResult.get());
        else result = result.concat(callbackResult);
      }
      return microM(result);
    }
  });

  global.microM = microM;
})(window);


microM.fn.printTo = function(id, descr) {
  document.getElementById(id).innerHTML += (descr ? descr + ": " : "") + JSON.stringify(this.get()) + '<br/>';
  return this;
}

microM.fn.square = function() {
  return this.pow(2);
}

var t = microM([2, 3, 4]).printTo('res', 'initial');
t.square().printTo('res', 'square')
  .map(function(el) {
    return microM(this + 10).square();
  }).printTo('res', 'mapped')
  .map(function(el) {
    return this instanceof Number;
  }).printTo('res', 'inside map: this instanceof Number');

<div id="res"></div>

这篇关于为什么在 jQuery 插件中使用 this 而不是 $(this)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆