浅谈JavaScript中的伪类 (李睿豪)

最近研究了一下JavaScript中的类,JS中的类还是很奇葩的,是伪类,类的实现是基于其原型继承机制的。写出来和大家分享一下!

一.JS类的建立方式是怎么样呢?它有哪几种建立方式呢?

(1).通过原型建立

function MyCreate(pro){
			if (pro === null) {
				throw TypeError();
			}
			if (Object.create) {
				return Object.create(pro);
			}
			var newV = function(){};
			var thisType = typeof pro;
			if(thisType !== 'function' && thisType !== 'object')
				throw TypeError();
			newV.prototype = thisType;
			return new newV();//在new 后的函数当成构造函数,通过new 创建对象
		}
		function NumberFW(fir_num,sec_num){
			var newDX = MyCreate(NumberFW.methods);
			newDX.from = fir_num;
			newDX.to = sec_num;
			return newDX;
		}
		NumberFW.methods = {
			includes:function(x){
				return this.from <= x && x <= this.to;
			},
			foreach:function(fun){
				if(typeof fun != 'function')
					throw TypeError();
				for(var i = this.from;i <= this.to; i++)
					fun(i);
				return this;
			}
		};

在JS中,类的所有实例对象都是从同一个原型对象上继承属性。因此,原型对象是类的核心!上面是一个通过原型建立的模型实例,MyCreate()函数是解决一些不支持Object.create浏览器的功能函数,它接受一个参数,返回以参数为原型的一个实例对象,在NumberPW函数中,接收两个参数,以NumberPw.methods为原型,创建一个newDX对象,然后初始化它返回!

需要注意的是:上面的例子中,原型属性作为函数的一个属性存储,它定义了所有“范围对象"所共享的方法!

(2).通过构造函数

使用关键字new来调用构造函数,使用new调用构造函数会自动创建一个新对象,此构造函数的作用只是初始化这个新对象。 还有必须要清楚地就是:通过构造函数创建对象会继承构造函数的prototype属性,也就是构造函数的prototype会当作新对象的原型。通过同一构造函数创建的对象的原型都相同,继承相同的属性。

说了这么多废话,来给大家看个实例:

	<script type="text/javascript">
		function MyCreate(fir_num,sec_num){
			this.from = fir_num;
			this.to = sec_num;
			//不需要返回
		} 
		MyCreate.prototype = {
			includes: function(x){
				return this.from <= x && x <= this.to;
			},
			foreach: function(fun){
				for(var i = this.from; i <= this.to;i++)
					fun(i);
				return this;
			}
		}//用new 创建的对象会 以 函数的prototype属性为原型,会继承它
	</script>

MyCreate()是构造函数,值得注意的一点:构造函数的首字母要大写~               通过构造函数创建的对象的原型是构造函数对象的prototype属性。

总结:通过new在构造函数调用之前已经创建了对象,实际上,构造函数只是当作只是当作新对象的一个方法调用的一次。那么构造函数的使命就是初始化这个新对象,所用使用this来初始化对象,注意,使用构造函数并不需要返回什么,因为它只是当作新对象的一个方法来初始化新对象!

(3)极简主义

	<span style="font-size:12px;"><script type="text/javascript">
		var Animal = {
			createNew: function(){
				var animal = {};
				animal.sleep = function(){
					console.log("打呼噜!");
				}
				return animal;
			}
		};
		var Cat = {
			likeEat : "fish", //公共共享的属性,只会被创建一次
			createNew: function(){
				var catVol = "喵喵喵" //<span style="color:#FF0000;">私有变量,其实就是只有在构造函数中才可以控制他,构造函数外不可操作它!</span>
				var cat = Animal.createNew(); <span style="color:#FF0000;">//继承!</span>
				cat.voice = function(){
					console.log(catVol);
				};
				cat.eatSome = function(){
					console.log("I like eat " + Cat.likeEat);
				};
				cat.setFood = function(food){
					Cat.likeEat = food;
				}
				return cat;
			}
		};
	</script>
</span>
    这种方式创建类,非常简单,上文例子中有Animal对象和Cat对象,他们都有createNew方法,每次只需要调用他们就可以创建一个实例对iang,createNew方法有一个特点,就是创建一个空对象,然后再函数里初始化它,最后返回它。 上面代码中有一个catVol,他是一个私有变量,通过闭包控制他,只有通过这个新对象的特权方法才能访问他!

二.子类的使用

(1).举个例子,如果B是A的子类,那么首先要确保B的原型对象继承A的原型对象。

	      function MyCreate(pro){
			if (pro === null) {
				throw TypeError();
			}
			if (Object.create) {
				return Object.create(pro);
			}
			var newV = function(){};
			var thisType = typeof pro;
			if(thisType !== 'function' && thisType !== 'object')
				throw TypeError();
			newV.prototype = thisType;
			return new newV();//在new 后的函数当成构造函数,通过new 创建对象
		}
		function Son(firstName,years){
			this.firstName = firstName;
			this.years = years;
		}
		function Father(lastName){
			this.lastName = lastName;
		}
		Father.prototype = {
			getName: function(){return this.firstName;}
		};
		Son.prototype = MyCreate(Father.prototype);//通过这样的给Son.prototype赋值,不会破坏Father.prototype的封装!
		Son.constructor = Son;
<span style="color:#FF0000;"><strong>Son.prototype = MyCreate(Father.prototype);
Son.constructor = Son;
<span style="color:#000000;">这两行是核心代码,让Son.prototype是以Father.prototype为原型对象,并且第二句意思是让Son.constuctor属性在指回Son构造函数!
</span></strong></span>
(2).另一种方法

	function Son(firstName,years){
			this.firstName = firstName;
			this.years = years;
	}
	function Father(lastName){
		this.lastName = lastName;
	};
	Father.prototype = {
		getName: function(){return this.firstName + this.lastName},
	};
	var try_this = new Father("li");
	Son.prototype = try_this;
	Son.prototype.constructor = Son;
        Father.prototype.getYear= function(){
        	return this.years;
        };
        try_this.lastName = "Smile";
        var me = new Son("ruihao",20);
	var you = new Son("jiahua",19);
第二张方法的核心代码:       

        var try_this = new Father("li");
        Son.prototype = try_this;
        Son.prototype.constructor = Son;

        这样确实可以!需要注意的是,无论创建多少次新的Son对象,这个Father只会创建一次,它又是Son的prototype ,所以会被所有的Son继承并且共享变量!

        这里更新Father.prototype,因为是动态的,并且将 Father的一个实例赋值给Son.prototype,其实赋的是   引用!!!
         me you这些实例的原型是Son.prototype,也就是Father的一个实例,但是在修改me you 这些实例中继承来的lastName时候,Father的那个实例确实不会修改,个人感觉,就是把Father    那个实例的属性浅复制到me 和 you 中!!



-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                                                                                                                                                                                                                                             作者: 李睿豪   2015.11.22


                                                      

                                                                                                                                                                                                      







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值