创建jQuery原型集合

时间:2017-03-16 12:43:15

标签: javascript jquery prototype

我需要在现有的jQuery元素集合上初始化某种原型。主要问题是原型应该只能在内部访问,并且可以在该集合上的内置jQuery函数(如.find())或该集合中的某些子对象上生成的元素上访问,例如:

var $a = $('a');
$a.__proto__.foo/*some magic over here*/ = function(){ alert('foo!'); };
$a.foo();            //should show alert('foo!')
$a.find('b').foo();  //should produce the same action
$('a').foo();        //should produce an error (method not found)

如果使用上面示例中的$a.__proto__,则会访问jQuery.prototype,因此该jQuery集合外部的所有新元素(例如$('a'))都授予访问权限到.foo()方法。在问题陈述中,这种行为是不可接受的。

这实际上是可能的吗?

1 个答案:

答案 0 :(得分:-1)

好的,事情就是这样,我有一个相当复杂的ES6解决方案,所以我无法深入解释它,但如果你有一些特别问题,请继续。

var wrap = (function wrapper() {
  var store = {};

  function wrap(fn) {
    return new Proxy(fn, {
      apply(target, thisArg, argumentsList) {
        var result = Reflect.apply(target, thisArg, argumentsList);

        // `jQuery(...)` returns a "rich" object that always contain `.length`
        if (result.length > 0) {
          result = new Proxy(result, {
            get(target, propertyKey, receiver) {
              var value = Reflect.get(target, propertyKey, receiver);

              if (Object.keys(store).includes(propertyKey)) {
                value = store[propertyKey];
              }

              return value;
            },

            set(target, propertyKey, value, receiver) {
              // TODO: use `Reflect.set(), somehow`
              // return Reflect.set(store, propertyKey, value, receiver);

              return (store[propertyKey] = value);
            },
          });
        }

        return result;
      }
    });
  }

  return wrap;
})();

var $ = wrap(jQuery);
$.prototype.find = wrap(jQuery.prototype.find); // TODO: implement recursively in `wrap()`


var x = $('div');
var xx = x.find('div');
var xxx = x.find('divvv');

xx.foo = 123;

console.log(x.foo);   // 123
console.log(xx.foo);  // 123
console.log(xxx.foo); // undefined