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

来源:互联网 发布:python mysql事务回滚 编辑:程序博客网 时间:2024/05/06 07:04

最近研究了一下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


                                                      

                                                                                                                                                                                                      







0 0