• javascript模拟类的最佳实践


    1:怎样模拟一个类

    在sencha touch2 系列里面定义一个类和new出这个类的对象

    Ext.define(
    	"Animal", {
    		config: {
    			name: null
    		},
    		constructor: function(config) {
    			this.initConfig(config);
    		},
    		speak: function() {
    			console.log('说点什么');
    		}
    	}
    )
    
    var my=Ext.create("Animal",{name:"bb"})
    my.speak();

    上面代码里面constructor在create的时候会自己主动调用。然后初始化config对象配置的属性。

    constructor全然就像面对象里面的构造函数……

    以下我模拟一下

    // 在sencha中new一个对象传了两个參数Ext.create("Animal",{name:"bb"})
    // 这里就不模拟sencha的命名空间了,所以生成该类的对象的时候传一个配置对象就可以
    // 把命名空间(mss)和命名单独提取出来,new mss.define({});
    var mss = {} //建立一个命名空间
    mss.define = function(config) {
    	if(typeof config !== 'object') {
    		console.log('參数错误');
    		return;
    	}
    	var interface = function() { //当new 该define返回的函数。会自己主动运行atrr和init
    		this.attr && this.attr();
    		this.init && this.init.apply(this, arguments);
    	}
    	for(var i in config) {
    		config.hasOwnProperty(i) &&(interface.prototype[i] = config[i]);
    	}
    	return interface;
    }
    
    var Car = mss.define({
    	attr: function() {
    		this.type = '汽车';
    	},
    	init: function() {
    		console.log(this.type);
    	},
    	speank: function() {
    		console.log('我是' + this.type);
    	}
    });
    
    var car1 = new Car();
    car1.speank();
    
    
    
    输出

    汽车
    我是汽车
    [Finished in 0.1s]


    这样就模拟成了:define一个类。然后new出来调用其方法;


    2:怎样在此基础上继承一个类

    首先看看sencha touch2系列的继承


    Ext.define(
    	"Person", {
    		extend: "Animal",
    		speak: function() {
    			console.log('我是人');
    		}
    	}
    )
    加多一个属性extend搞定。

    以下在mss.define模拟一下

    // 在sencha中new一个对象传了两个參数Ext.create("Animal",{name:"bb"})
    // 这里就不模拟sencha的命名空间了。所以生成该类的对象的时候传一个配置对象就可以
    // 把命名空间(mss)和命名单独提取出来,new mss.define({});
    var _mss = {} //建立一个命名空间
    _mss.Define = function(parClass, curConfig) {
    
    
    	// 若sup 是个object,表示这是一个新类
    	// 若sup 是个function,表示这是一个继承
    	if(typeof parClass === 'object') {
    		curConfig = parClass;
    		parClass = function() {};
    	}
    	// 定义返回类
    	// 当new 该define返回的函数。会自己主动运行atrr和init
    	var interface = function() { 
    		this.attr && this.attr();
    		this.init && this.init.apply(this, arguments);
    	}
    	// 返回类继承 parClass
    	interface.prototype = new parClass();
    
    	// 为返回类包括的两个初始化函数定义基础方法
    	// 获得继承的init方法 和attr方法
    	// 假设parClass存在init方法,那么nterface.prototype.init
    	// 和new parClass().init相等
    	var parInit = interface.prototype.init || function() {};
    	var curInit = curConfig.init || function() {};
    	var parAttr = interface.prototype.attr || function() {};
    	var curAttr = curConfig.attr || function() {};
    
    	// 为返回类原型初始化当前属性,这里注意可能被后面的方法重写
    	for(var i in curConfig) {
    		curConfig.hasOwnProperty(i) && (interface.prototype[i] = curConfig[i]);
    	}
    
    	// 假设当前返回类已经继承了init,重写该方法
    	if(arguments.length && arguments[0].prototype && arguments[0].prototype.init === parInit) {
    		interface.prototype.init = function() {
    			var scope = this;
    			var args = [function() {
    				parInit.apply(scope, arguments);
    			}];
    			var slice = [].slice;
    			curInit.apply(scope, args.concat(slice.call(arguments)));
    
    		}
    	}
    
    
    	// 假设当前返回类已经继承了attr,重写attr 或者是首次构造改方法(新类)
    	interface.prototype.attr = function() {
    		parAttr.call(this);
    		curAttr.call(this);
    	}
    
    	// 继承父类的成员属性
    	for(var i in parClass) {
    		parClass.hasOwnProperty(i) && (interface[i] = parClass[i]);
    	}
    
    	return interface;
    }
    
    var Car = _mss.Define({
    	attr: function() {
    		this.type = '汽车';
    	},
    	init: function() {
    		console.log(this.type);
    	},
    	speank: function() {
    		console.log('我是' + this.type);
    	}
    });
    
    var car1 = _mss.Define(Car, {
    })
    new car1().speank();
    
    
    
    

    输出

    汽车
    我是汽车
    [Finished in 0.1s]

    对于call实现继承

    	interface.prototype.attr = function() {
    		parAttr.call(this);
    		curAttr.call(this);
    	}

    在Chorome控制台打印这段代码就能够解释一下这段代码了

    var _Attr = function() {
      this.a = 1;
    }
    var B = function() {
      this.attr();
    };
    B.prototype.attr = function(){_Attr.call(this);}
    console.log(new B());
    	
    
    VM665:9 B {a: 1}a: 1__proto__: Battr: (){_Attr.call(this);}constructor: () {__proto__: Object


  • 相关阅读:
    关于Maven项目build时出现No compiler is provided in this environment的处理
    freemaker的函数使用
    FTP在docker容器中上传失败解决,改为被动模式
    linux重定向及nohup不输出的方法
    手动抠下的wordpress登录页面样式
    使用后端生成图片验证码流文件(不推荐)
    部署到docker容器后图片验证码显示不出来
    Linux修改profile文件改错了,恢复的方法
    DotNETCore 学习笔记 异常处理
    DotNETCore 学习笔记 路由
  • 原文地址:https://www.cnblogs.com/claireyuancy/p/6991583.html
Copyright © 2020-2023  润新知