首先吐槽一句,今年的就业形势很不乐观啊,特别是搞.net的(相对java),特特别是还没出校门没有正式工作经验的,找个实习很难,前些天接了个面试电话,上来就质疑我“你一个在校大学生怎么可能做了那么多项目呢,你的简历是真实的吗?这些项目你做的是核心工作吗?”,语气中充满了质疑,我只能生硬的回答着“嗯啊”,这个时候去解释或许太苍白了,我深知年轻人很难受到别人信任。当然了冷静下来想想,现在这个社会留给年轻人的机会本来就不多,就算你在大学里学了不少东西,做了不少东西,相对于前辈来讲还是有大差距的,经历点挫折是应该的嘛,不怨天不尤人,继续坚持下去吧。

蛋疼的日子总要做点事的,最近想把自己写的一些js常用功能封装成自己的一个库,于是乎学习了一下jquery框架的整体架构,收获颇多,接着又看了看百度编辑器的核心js库,发现其中一段javascript模拟继承的代码,用的地方还挺多,闲得无聊分析一下吧。

引起我注意的来自百度编辑器js库中的一段注释

  /**
* 模拟继承机制,subClass继承superClass
* @name inherits
* @grammar UE.utils.inherits(subClass,superClass) => subClass
* @example
* function SuperClass(){
* this.name = "小李";
* }
* SuperClass.prototype = {
* hello:function(str){
* console.log(this.name + str);
* }
* }
* function SubClass(){
* this.name = "小张";
* }
* UE.utils.inherits(SubClass,SuperClass);
* var sub = new SubClass();
* sub.hello("早上好!"); ==> "小张早上好!"
*/

要说大厂就是大厂,注释写的非常规范,可以让新人很快参与到项目中来。(顺便吐槽一句,.net开发者想进百度很难啊,内部有些办公系统也不招聘实习生,想进电商实现也很难啊,因为基本上没有.net平台了...)。

建议先看一下prototype的用法(参考http://blog.sina.com.cn/s/blog_7045cb9e0100rtoh.html

首先我们来看一个列子

//定义一个父类
function SuperClass() {
this.name = "小李";
this.age = "15";
}
//父类通过prototype给自己增加了一个hello方法
SuperClass.prototype = {
hello: function (str) {
console.log("hello:"+this.name + str);
} }
//父类通过prototype给自己增加了一个sex属性
SuperClass.prototype.sex = "男";
//父类通过prototype给自己增加了一个指向一个对象(数组对象)的属性arr,这里强调一下,这里指向的是一个对象,待会测试有用。
SuperClass.prototype.arr = new Array("a", "b");
//定义一个子类
function SubClass() {
this.name = "小张";
this.address = "北京"; }
//将父类的方法属性克隆过来
SubClass.prototype = new SuperClass();
//创建一个子类对象
var son = new SubClass();
//这样我们的son遍具有了hello方法
son.hello("你好");
//我们生成另一个子类实例,改变name和arr
var son2 = new SubClass();
son2.name="小红";
son2.arr.push("cc");
console.log(son.name);//值未变
console.log(son.arr);//输出a,b,cc也就是说父类中的属性如果指向的是对象,则子类的实例将会共享这个对象。

上面的列子中 SubClass.prototype = new SuperClass();   这句起到了关键的作用,它把父类的方法属性克隆给了子类。但是会带来一个问题,那就是假如子类的定义中使用了js框架中流行的构造函数/原型方式,如下:

   function SubClass() {
this.name = "小张";
this.address = "北京";
}
SubClass.prototype.add = function () {
console.log("add:"+this.name);
}

这就是传说中的联合创建类的方法,就是用构造函数/原型方式就可以像其他程序设计语言一样创建对象,用构造函数定义对象的非函数属性,用原型方式定义对象的方法。 很多js框架中都在用这种方法,这种方法效率较高,节约内存。

然而当在子类定义之后写上 SubClass.prototype = new SuperClass();以后,会覆盖掉自己定义的add方法,这样子类的这句定义

SubClass.prototype.add = function () {

console.log("add:"+this.name);

}

就必须写到SubClass.prototype = new SuperClass(); 之后了。这样显然给我们使用带来了麻烦,每次定义子类这种用法的时候还得考虑一个顺序问题,实在不方便。我们看看百度编辑器的js核心库是怎么解决的

为了分析方便,我把它的js模拟继承的代码抽离出来,原来一些以json方式组织的函数单独放到一个新的html页面里做测试。以下是我抽离出来的和模拟继承有关的代码:

 //定义一个父类
function SuperClass() {
this.name = "小李";
this.showMsg = function () {
alert("baseClass::showMsg");
} } SuperClass.prototype = {
hello: function (str) {
console.log(this.name + str);
} }
SuperClass.prototype.sex = "男";
SuperClass.prototype.arr = new Array("a", "b");
//定义子类
function SubClass() {
this.name = "小张"; }
//子类通过联合创建方式增加了add方法
SubClass.prototype.ddd = function () { console.log(this.name); }
//可以在定义完成之后,在需要继承的时候写上一下语句来开始继承操作
inherits(SubClass, SuperClass);
//生成一个子类实例
var sub = new SubClass();
sub.hello("早上好!");//父类的hello可以使用
sub.ddd(); //子类的ddd方法可以使用了
sub.arr.push("cc");
var sub1 = new SubClass();
console.log(sub1.arr);//sub1和sub共享了arr,需注意。

相应的extend,inherits和makeInstance方法

        //将原型s中的属性复制给一个对象t
function extend(t, s, b) {
if (s) {
// console.log(s);
for (var k in s) {
//下面用到了hasOwnProperty,用来判断一个对象是否有你给出的属性或对象
if (!b || !t.hasOwnProperty(k)) {
t[k] = s[k];
}
}
}
return t;
}
function inherits(subClass, superClass) {
var oldP = subClass.prototype,
newP = makeInstance(superClass.prototype); //返回父类由原型方法生成实例对象,这里并没有返回整个父类对象实例,而是根据父类原型生成了一个对象,这样父类构造函数中的成员屏蔽掉了,子类无法继承。
console.log(newP);
extend(newP, oldP, true); //通过这一步,子类在原型中定义的属性赋给了父类原型生成的对象
subClass.prototype = newP;//通过这一步,子类原型被重新构造,包括了自己原来的属性和父类原型中的属性。
return (newP.constructor = subClass);
}
function makeInstance(obj) {
var noop = new Function();
noop.prototype = obj;
obj = new noop;
noop.prototype = null;
return obj;
}
这里要说一句,这篇文章介绍的模拟继承方法只能将父类原型中的属性,比如上面的hello方法可以继承给子类,或者父类原型再添加一个性别属性比如SuperClass.prototype.sex = "男";这里的sex同样可以传递给子类,但是父类构造函数中的成员无法继承给子类,子类必须重新定义。也就是说父类构造函数中定义的属性可以认为是“private”的,父类原型中定义的是”public“的,所以如果父类的属性想让子类继承,最好定义到原型中。这时特别要注意如果父类原型中的成员指向一个对象时,比如 SuperClass.prototype.arr = new Array("a", "b"); 所有子类的实例将会共享这个arr属性。

总结它的这个逻辑也就一句话,把子类原型中的成员给了父亲原型的一个实例对象,这个实例对象得到了扩充,然后清空子类原型,最后把这个扩充的对象中的成员克隆给子类原型。

好了,扯淡了半天把自己都扯晕了,我是有多无聊啊。赶紧来个单位把我这妖孽收了吧。

Javascript模拟继承(赠送.net吐槽一段)的更多相关文章

  1. javascript模拟继承

    javascript作为前端开发的标配技能,如果不掌握好它的三大特点:1.原型 2.作用域 3. 闭包 ,又怎么可以说你学好了这门语言呢?如果标配的技能都没有撑握好,怎么可以任性的玩耍呢?怎么验证自己 ...

  2. javascript实现继承3种方式: 原型继承、借用构造函数继承、组合继承,模拟extends方法继承

    javascript中实现继承的三种方式:原型继承.借用构造函数继承.混合继承: /* js当中的继承 js中 构造函数 原型对象 实力对象的关系: 1 构造函数.prototype = 原型对象 2 ...

  3. Javascript原型继承容易忽略的错误

    编写Javascript的开发者都知道,JS虽然没有类(ES6添加了class语法),但是可以模拟出OOP语言的类和面向对象的概念,比如我们都知道的一句话,Javascript中处处是对象,而面向对象 ...

  4. JavaScript 的继承与多态

    本文先对es6发布之前javascript各种继承实现方式进行深入的分析比较,然后再介绍es6中对类继承的支持以及优缺点讨论.最后介绍了javascript面向对象编程中很少被涉及的“多态”,并提供了 ...

  5. 详解Javascript的继承实现(二)

    上文<详解Javascript的继承实现>介绍了一个通用的继承库,基于该库,可以快速构建带继承关系和静态成员的javascript类,好使用也好理解,额外的好处是,如果所有类都用这种库来构 ...

  6. [原创]Javascript模拟“类”的综合实现方式以及部分细节【截至ES6】

    [原创]Javascript模拟“类”的综合实现方式以及部分细节[截至ES6] 前言   最近几个旧项目里使用的图片编辑插件出现Bug, 经Review 后确定需要在其内外均做些改动,但是头疼的发现部 ...

  7. JavaScript原型继承工作原理

    原型继承的定义 当你阅读关于JS原型继承的解释时,你时常会看到以下这段文字: 当查找一个对象的属性时,JavaScript 会向上遍历原型链,直到找到给定名称的属性为止.——出自JavaScript秘 ...

  8. JavaScript(7)--- 继承

    JavaScript(7)--- 继承 概念 首先继承是一种关系,类(class)与类之间的关系,JS中没有类,但是可以通过构造函数模拟类,然后通过原型来实现继承,继承也是为了数据共享. 之间有讲过j ...

  9. JavaScript之继承(原型链)

    JavaScript之继承(原型链) 我们知道继承是oo语言中不可缺少的一部分,对于JavaScript也是如此.一般的继承有两种方式:其一,接口继承,只继承方法的签名:其二,实现继承,继承实际的方法 ...

随机推荐

  1. FABRIC单机开发者模式启动

    在开始之前需要导出一个自定义变量,方便后续操作: export FABRIC=/opt/gopath/src/github.com/hyperledger/fabric/devenv 1.在真机上执行 ...

  2. c#接口与抽象类的区别

    abstract 修饰符用于表示所修饰的类是不完整的,并且它只能用作基类.抽象类与非抽象类在以下方面是不同的: 抽象类不能直接实例化,并且对抽象类使用 new 运算符是编译时错误.虽然一些变量和值在编 ...

  3. acm入门 杭电1001题 有关溢出的考虑

    最近在尝试做acm试题,刚刚是1001题就把我困住了,这是题目: Problem Description In this problem, your task is to calculate SUM( ...

  4. [ACM训练] 算法初级 之 基本算法 之 枚举(POJ 1753+2965)

    先列出题目: 1.POJ 1753 POJ 1753  Flip Game:http://poj.org/problem?id=1753 Sample Input bwwb bbwb bwwb bww ...

  5. 弱省互测#0 t2

    题意 给定两个字符串 A 和 B,求下面四个问题的答案: 1.在 A 的子串中,不是 B 的子串的字符串的数量. 2.在 A 的子串中,不是 B 的子序列的字符串的数量. 3.在 A 的子序列中,不是 ...

  6. js中创建对象的三种方式

    1. 对象字面量 var obj={ name:"小小", age:3, car:{ brand:"baoma", } }; } 2.使用内置构造函数 var ...

  7. js 继承 对象方法与原型方法

    js函数式编程确实比很多强语言使用灵活得多,今天抽了点时间玩下类与对象方法调用优先级别,顺便回顾下继承 暂时把原型引用写成继承 先看看简单的两个继承 var Parent = function(){} ...

  8. MVC项目中ExecutionTimeout不生效的解决方案

    我们做web服务器端开发时,经常会遇到一个需求场景,因为某些耗时处理造成页面的响应处理时间超长,技术角度就想能否给页面处理程序一个指定的超时时间,服务端处理程序执行时间超过这个指定的超时时间则中断处理 ...

  9. rinetd

    1.安装 tar zxvf rinetd.tar.gz    make    make install 2.设置 vi /etc/rinetd.conf 0.0.0.0 8080 172.19.94. ...

  10. asp.net mvc引用控制台应用程序exe

    起因:有一个控制台应用程序和一个web程序,web程序想使用exe程序的方法,这个时候就需要引用exe程序. 报错:使用web程序,引用exe程序 ,vs调试没有问题,但是部署到iis就报错,如下: ...