Why this and not $(this) in jQuery plugins

后端 未结 2 1600
陌清茗
陌清茗 2021-01-13 18:45

The docs tell us:

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 functio

2条回答
  •  一整个雨季
    2021-01-13 19:35

    Let's try see a bit deeper:

    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);
    

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

    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);
    }
    

    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;

    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);
    

    where first param in call function - is 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()) + '
    '; 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');

提交回复
热议问题