博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
分析JQ作者的类实现过程
阅读量:6592 次
发布时间:2019-06-24

本文共 5309 字,大约阅读时间需要 17 分钟。

作为jquery的作者。John Resig在博客里记录了一种class的实现,原文

下面是源码:

(function(){  var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;   this.Class = function(){};  Class.extend = function(prop) {    var _super = this.prototype;    initializing = true;    var prototype = new this();    initializing = false;       for (var name in prop) {      prototype[name] = typeof prop[name] == "function" &&        typeof _super[name] == "function" && fnTest.test(prop[name]) ?        (function(name, fn){          return function() {            var tmp = this._super;            this._super = _super[name];            var ret = fn.apply(this, arguments);            this._super = tmp;            return ret;          };        })(name, prop[name]) : prop[name];    }       function Class() {      if ( !initializing && this.init ){		this.init.apply(this, arguments); 	  }    }	    Class.prototype = prototype;    Class.prototype.constructor = Class;    Class.extend = arguments.callee;       return Class;  };  })();复制代码

我们把调用方法带入进去看看其到底是怎么实现的。

var Person = Class.extend({  init: function(isDancing){    this.dancing = isDancing;  },  dance: function(){    return this.dancing;  }});因此prop = {  init: function(isDancing){    this.dancing = isDancing;  },  dance: function(){    return this.dancing;  }}var _super = 超级父类的原型对象var prototype = 由超级父类生成的实例initializing = false;**第一次for循环** typeof prop["init"] == "function" // true typeof _super["init"] == "function" // false typeof fnTest.test(function(isDancing){
this.dancing = isDancing;}) // false**循环结束后,所以** prototype["init"] = prop["init"]; prototype["dance"] = prop["dance"]子类: function Class(){ if(!initializing && this.init){ this.init.apply(this, arguments); } } // 赋值原型链,完成继承 Class.prototype = prototype; // 改变constructor的指向 Class.prototype.constructor = Class; // 为子类Class添加extend方法 Class.extend = arguments.callee; // 返回子类 return Class; 因此 Person = 返回的子类Class; 而子类Class 此时的this指向超级父类Class function Class(){ if(!initializing && this.init){ this.init.apply(this, arguments); } } Class.prototype = { constructor: 指向自身的构造函数Class init: function(isDancing){
this.dancing = isDancing}, dance: function(){ return this.dancing;} } Class.extend方法与超级父类相同调用,使用Person构造函数,创建一个实例。 var p = new Person(true); 当new Person()时,实际上调用的是 返回的子类Class 此时this指向刚刚创建生成的实例p, 因此if条件为真,执行 this.init.apply(this,arguments) init: function(true){
this.dancing = true;} 此时调用p.dance();则其输出为true复制代码

此时,Person类指向子类Class

function Class(){	if(!initializing && this.init){		this.init.apply(this, arguments);	}} Class.prototype = {	constructor: 指向自身的构造函数Class	init: function(isDancing){this.dancing = isDancing},	dance: function(){ return this.dancing;}}Class.extend方法与超级父类相同复制代码

当基于Person进行继承时

var QdGithub = Person.extend({  init: function(){    this._super( false );  },  dance: function(){    // Call the inherited version of dance()    return this._super();  },  swingSword: function(){    return true;  }});  因此 var _super = Person的原型对象 var prototype = Person类生成的实例 initializing = false;** 第一次for循环:** typeof prop["init"] == "function"   // true typeof _super["init"] == "function"  // true fnTest.test(function(){
this._super(false)}) // true 因此进入闭包,把Person类的对象属性方法混入子类上。 参数: name: "init" fn: function(){
this._super(false)} 返回匿名函数 prototype["init"] = function(){ var tmp = this._super; this._super = function(isDancing){
this.dancing = isDancing;}; fn = function(){
this._super(false)}; var ret = fn.apply(this, arguments); this._super = tmp; return ret; } 第二次循环同第一次循环 prototype["dance"] = function(){ var tmp = this._super; this._super = function(){ return this.dancing;} fn = function(){
return this._super();} var ret = fn.apply(this, arguments); this._super = tmp; return ret; } 第三次循环 prototype["swingSword"] = function(){
return true;}返回子类function Class(){ if(!initializing && this.init){ this.init.apply(this, arguments); }} Class.prototype = { constructor: 指向自身的构造函数Class init: function(){ var tmp = this._super; this._super = function(isDancing){
this.dancing = isDancing;}; fn = function(){
this._super(false)}; var ret = fn.apply(this, arguments); this._super = tmp; return ret; }, dance: function(){ var tmp = this._super; this._super = function(){ return this.dancing;} fn = function(){
return this._super();} var ret = fn.apply(this, arguments); this._super = tmp; return ret; }, swingSword: function(){
return true;}}Class.extend方法与超级父类相同因此:QdGithub = 返回的子类Class(就是上面刚刚分析,返回的子类Class) 调用,使用QdGithub构造函数,创建一个实例。 var n = new QdGithub(true); 当new QdGithub()时,实际上调用的是 返回的子类Class 此时this指向刚刚创建生成的实例n, 因此if条件为真,执行 this.init.apply(this,arguments),把实例n的dancing属性设置为false init: function(){ var tmp = this._super; this._super = function(isDancing){
this.dancing = isDancing;}; fn = function(){
this._super(false)}; var ret = fn.apply(this, arguments); this._super = tmp; return ret; } 此时调用n.dance();则其输出为false 此时调用n.swingSword();则其输出为true // Should all be truep instanceof Person && p instanceof Class &&n instanceof Ninja && n instanceof Person && n instanceof Class 复制代码

【一起探讨,微信公众号:qdgithub】

转载于:https://juejin.im/post/5b9b7906e51d450e615ff381

你可能感兴趣的文章
[LeetCode] Student Attendance Record I
查看>>
PHP回顾之多进程编程
查看>>
spring boot + redis
查看>>
Ajax技术细节
查看>>
nuxt.js部署vue应用到服务端过程
查看>>
删除数组中的指定元素 | JavaScript
查看>>
CSS3+JS实现静态圆形进度条【清晰、易懂】
查看>>
关于树形插件展示中数据结构转换的算法
查看>>
图片加载框架之Fresco
查看>>
Spotify开源其Cassandra编排工具cstar
查看>>
高性能web建站规则(将js放在页面底部)
查看>>
Java EnumMap工作原理及实现
查看>>
阐述Spring框架中Bean的生命周期?
查看>>
虚拟内存管理
查看>>
注水、占坑、瞎掰:起底机器学习学术圈的那些“伪科学”
查看>>
大数据小视角1:从行存储到RCFile
查看>>
JavaScript常用设计模式
查看>>
第18天:京东网页头部制作
查看>>
好消息:Dubbo & Spring Boot要来了
查看>>
面向对象封装的web服务器
查看>>