为什么这个而不是jQuery插件中的$(this)

时间:2015-05-27 09:37:42

标签: jquery jquery-plugins

The docs告诉我们:

  

让我们说我们想要创建一个插件,使文本在一组中   检索元素绿色。我们所要做的就是添加一个名为的函数   绿化到$ .fn,它将像任何其他jQuery一样可用   对象方法。

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


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

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

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

2 个答案:

答案 0 :(得分:2)

让我们试试看更深一点:

让我们尝试生成一个非常简化的版本库,比如jQuery,并将其命名为例如 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);

所以我们有一个最简单的lib看起来像jQuery。现在我们想要添加“插件”,例如函数 square

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

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

这里我们可以直接从这个调用 pow ,因为在这种情况下 microM 这个实例,以及 microM.prototype 中的所有函数都可以直接使用;

但是当我们调用 map 函数在回调中进行回调时,这个将是具体的元素,例如Number原语,因为我们称之为

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

call function中的第一个参数 - thisArg

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

(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>

答案 1 :(得分:1)

  

我们不是要使用$(el).css()来正常设置jQuery中的CSS吗?

是的,在元素的上下文中。

然而在

$.fn.greenify = function() {
    // 'this' is a jQuery object at this point - with all the jQuery functions
    this.css( "color", "green" );
};

greenify具有 css功能的同一对象的一部分。

在其他地方,有一个

$.fn.css = function() {
       ...
    };

cssgreenify都是prototype $。fn

的一部分

请参阅jQuery: What's the difference between '$(this)' and 'this'?https://remysharp.com/2007/04/12/jquerys-this-demystified