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

详细的call用法见:http://www.cnblogs.com/wangtao_20/archive/2011/01/01/1923918.html or http://uule.iteye.com/blog/1158829

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-12 06:58:58

javascript模拟类的最佳实践的相关文章

JavaScript 高级程序设计之最佳实践

一.可维护性:可理解性.直观性.可适应性.可扩展性.可调试性 代码约定: 可读性 格式化:建议缩进大小为4个空格 注释:函数和方法.大段代码.复杂的算法.hack 变量和函数命名 变量名为名词 函数名为动词开始 变量和函数使用合符逻辑的名字,不要担心长度. 变量类型透明:表示变量类型的三种方式 初始化: var found = false; //布尔型 使用匈牙利标记法来指定变量类型:o代表对象,s代表字符串,i代表整数,f代表浮点数,b代表布尔型 使用类型注释: var found /*:Bo

javascript模拟类及类继承

// 模拟Class function Rectangle(width, height){ this.height = height; // 实例变量(public) this.getWidth = function(){ return width; } // 实例变量(private) this.setWidth = function(w){ width = w; } Rectangle.INSTANCE_COUNT++; } Rectangle.prototype.getSize = fun

JavaScript 最佳实践

这个文档是基于JavaScript社区众多开发者的意见和经验,在开发JavaScript代码上的最佳实践和首选的方案的明细表.因为这是一个推荐的表而非原则性的方案,经验丰富的开发者可能对下面的表达会有略有不同的见解. 1. 总是使用 ‘var’ 在JavaScript中,变量不是全局范围的就是函数范围的,使用”var”关键词将是保持变量简洁明了的关键.当声明一个或者是全局或者是函数级(function-level)的变量,需总是前置”var”关键词,下面的例子将强调不这样做潜在的问题. 不使用

Javascript定义类(class)的三种方法

注:本文转自阮一峰,觉得此篇文章对我对大家有帮助,因此转过来. 将近20年前,Javascript诞生的时候,只是一种简单的网页脚本语言.如果你忘了填写用户名,它就跳出一个警告. 如今,它变得几乎无所不能,从前端到后端,有着各种匪夷所思的用途.程序员用它完成越来越庞大的项目.Javascript代码的复杂度也直线上升.单个网页包含10000行Javascript代码,早就司空见惯.2010年,一个工程师透露,Gmail的代码长度是443000行! 编写和维护如此复杂的代码,必须使用模块化策略.目

45个实用的JavaScript技巧、窍门和最佳实践

如你所知,JavaScript是世界上第一的编程语言,它是Web的语言,是移动混合应用(mobile hybrid apps)的语言(比如PhoneGap或者Appcelerator),是服务器端的语言(比如NodeJS或者Wakanda),并且拥有很多其他的实现.同时它也是很多新手的启蒙语言,因为它不但可以在浏览器上显示一个简单的alert信息,而且还可以用来控制一个机器人(使用nodebot,或者nodruino).掌握JavaScript并且能够写出组织规范并性能高效的代码的开发人员,已经

Javascript继承的最佳实践

什么是继承? 继承是面向对象最显著的一个特性.继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力. 在Javascript 中 没有 类的概念, 它是通过构造函数来产生 对象, 构造函数 就是一个普通的函数,通常当函数名 为 大写开头的,我们认为是构造函数,否则 就是普通的方法. function A() { this.name = 'A Class instance'; } function m1() { } 既然 Javascript 是 通过构造函数来产生

实用的JavaScript技巧、窍门和最佳实践

1 – 在第一次给一个变量赋值的时候不要忘记使用var关键字 给一个未定义的变量赋值会导致创建一个全局变量.要避免全局变量. 2 – 使用===,而不是== ==(或!=)操作符在需要的时候会自动执行类型转换.===(或!==)操作不会执行任何转换.它将比较值和类型,而且在速度上也被认为优于==. 1 2 3 4 5 6 7 8 [10] === 10    // is false [10]  == 10    // is true '10' == 10     // is true '10'

【译】JavaScript 创建对象: 方法一览与最佳实践

本文是我在众成翻译上认领并翻译的:JavaScript 创建对象: 方法一览与最佳实践 在JavaScript中“创建对象”是一个复杂的话题.这门语言提供了很多种创建对象的方式,不论新手还是老手都可能对此感到无所适从,不知道应该选择哪一种.不过,尽管创建对象的方法很多,看上去语法差异也很大,但实际上它们的相似性可能比你所以为的要多.本文将带领你踏上一段梳理对象创建方法的旅程,为你揭示不同方法之间的依赖与递进关系. 对象字面量 我们的第一站毫无疑问就是创建对象最简单的方法,对象字面量.JavaSc

给javascript初学者的24条最佳实践

1.使用 === 代替 == JavaScript 使用2种不同的等值运算符:===|!== 和 ==|!=,在比较操作中使用前者是最佳实践. “如果两边的操作数具有相同的类型和值,===返回true,!==返回false.”——JavaScript:语言精粹 然而,当使用==和!=时,你可能会遇到类型不同的情况,这种情况下,操作数的类型会被强制转换成一样的再做比较,这可能不是你想要的结果. 2.Eval=邪恶 起初不太熟悉时,“eval”让我们能够访问JavaScript的编译器(译注:这看起