jQuery的无new构建类 理解向笔记

是读这篇文章后的复读哒。主要结合评论区#54#82理了一遍demo,非常浅显初心向所以读懂上文就能关闭这篇东西辣。
理解不当、错漏之处恳请斧正!

目标:根据jQuery的思路实现不用new实例化对象

首先用函数实现类,常规的方法:

var aQuery = function(age) {
}
aQuery.prototype = {
  name: function(){},
  age: 18
}
var a = new aQuery();
a.age; // 返回18

但jQuery未在外面用new就可以实例化对象,也就是让函数直接返回实例:

var aQuery = function(age) {
  return new aQuery(); // ←把new放进函数了!
}
aQuery.prototype = {
  name: function(){},
  age: 18
}
aQuery().age; // 但是,死循环了!

为了返回正确的实例,把aQuery类当作一个工厂方法,放到aQuery.prototype中来创建实例:

var aQuery = function(age) {
  return aQuery.prototype.init(); // ←专门搞个init来返回了!
}
aQuery.prototype = {
  init: function() {
    return this;
  },
  name: function(){},
  age: 18
}
aQuery().age; // 返回18了!

但是,此时init中的this指向aQuery类,若把init函数也当作一个构造器,aQuery的prototype会被改变:

var aQuery = function(age) {
  return aQuery.prototype.init(age);
};
aQuery.prototype = {
  init: function(s) {
      if (s) this.age = s; // ←age被改了!
      return this;
  },
  name: function(){},
  age: 18
};
var a = aQuery().age; // 未传值,根据原型对象的值,age是18
var b = aQuery(16).age; // 原型对象的age变为16
var c = aQuery(17).age; // 原型对象的age变为17
var d = aQuery().age; // 未传值,age仍为17不变
// “this指向aQuery的原型prototype,aQuery()得到的始终就是aQuery.prototype”,执行后aQuery()的age变为17

因此,要通过实例化init函数,让每个this指向各自的实例化对象:

var aQuery = function(age) {
  return new aQuery.prototype.init(age); // ←又把new放进来了!
};
aQuery.prototype = {
  init:function(s){
      if (s) this.age = s;
      return this;
  },
  name:function(){},
  age:18
};
var a = aQuery().age; // 未传值,返回undefined
var b = aQuery(16).age; // 传入16,返回16
var c = aQuery(17).age; // 传入17,返回17
var d = aQuery().age; // 未传值,返回undefined
// “this指向aQuery.prototype.init的实例, aQuery()得到的结果是aQuery.prototype.init的实例”,执行后aQuery()的age为undefined

但这样就访问不到aQuery的原型对象了_(:з」∠)_。
为了让this各回各家的同时能够使用aQuery原型对象上的属性和方法,jQuery的骚操作出现了!

var aQuery = function(age) {
  return new aQuery.prototype.init(age);
};
aQuery.prototype = {
  init:function(s){
      if (s) this.age = s;
      return this;
  },
  name:function(){},
  age:18
};
aQuery.prototype.init.prototype = aQuery.prototype; // ←把aQuery的prototype赋给init的prototype!
var a = aQuery().age; // 未传值,新生成的实例上没有age,访问原型对象的值,得到18
var b = aQuery(16).age; // 传入16,返回16
var c = aQuery(17).age; // 传入17,返回17
var d = aQuery().age; // 未传值,新生成的实例上没有age,访问原型对象的值,得到18
// “将init的原型和aQuery的原型关联起来,从而通过aQuery()能够访问到aQuery.prototype的属性”,执行后aQuery()的age本身应为undefined,访问原型对象得到18

到这里差不多了……差不多了吧?

posted @ 2020-03-25 19:13  su0tiuqibu  阅读(183)  评论(0编辑  收藏  举报