美文网首页
JavaScript继承指迷

JavaScript继承指迷

作者: Airsola | 来源:发表于2016-10-28 20:58 被阅读47次

    以下是 廖雪峰老师 JavaScript 教程的笔记 ,这个章节有点大雾,这里记录一下

    先硬广 安利一下

    小A和小B都是应届毕业生,一起进入了一家互联网公司做前端。半年过去了,小A进步神速,他写的JavaScript代码在组里挑剔的的老员工看来都挺不错:

    可读性好,模块化程度高,而且有大量的测试。反观小B,他的代码总是一团糟,还经常搞出莫名其妙的bug。每次做code review时,大家对小B的代码都特别头疼。

    年底考核的时候,组长让小A分享一下他入职以来是怎么学习前端并快速成长的,小A不好意思地给大家分享了自己的一点学习心得:

    首先,前端工程师必须得熟练掌握HTML、CSS和JavaScript。只懂其中一个或两个不行,必须对这三个都很熟悉,尤其是JS。

    很多前端工程师还把对JS的认识停留在用jQuery做网页动画的时代,这个认识早就落后了,现在JS不仅负责前端的所有页面逻辑,还能利用Node开发后端服务。

    而JS并没有看上去那么简单,它入门容易精通难,尤其是自己摸索,或者在网上随便搜索一些代码片断,很容易被带进沟里。学JavaScript应该学到精髓,还应该知道JS不好的设计,并且有意识地只用JS优秀的设计。

    由于JS最近随着HTML5的兴起有了很大的更新,网上很多教程或者资料都过时了,现在应该用ES 6标准来写代码。即使不做后端,也要对Node非常熟悉,因为前端的自动化也是基于Node和npm实现的。

    小A说了这么多,组长觉得很惊讶,说,“我看你平时也没怎么与老员工探讨前端技术问题,怎么懂得这么多?知识体系还挺丰富!”

    小A不好意思地说,“其实我刚进公司的时候也是啥也不会,纯小白一个,偶然听一个朋友推荐看到了廖雪峰老师的网站,里面有非常系统的JavaScript全栈教程,讲的重点都是JS的精髓,还特别指出容易出错的坑。廖老师的教程更新很快,我每天都花半个小时上去学一点,几个月下来也积累了不少。”

    组长用自己的笔记本搜索了小A说的廖雪峰老师的网站,看了几页,说:“小A啊,这么好的JS教程,你怎么藏着掖着,不早点分享给大家呢?你这个做法不厚道,今晚团队聚餐的费用必须你出。”

    小A一脸懵逼……

    友情提示:小A提到的神奇的JavaScript全栈教程哪里找?猛戳这里**有惊喜!

    创建对象

    构造函数

    为了区分普通函数和构造函数,按照约定,构造函数首字母应当大写,而普通函数首字母应当小写

    function Student(name) {
        this.name = name;
        this.hello = function () {
            alert('Hello, ' + this.name + '!');
        }
    }
    

    搭配 new 使用默认 自动返回 this

    var xiaoming = new Student('小明');
    xiaoming.name; // '小明'
    xiaoming.hello(); // Hello, 小明!
    
    var xiaohong = new Student('小红');
    xiaohong.name; // '小明'
    xiaohong.hello(); // Hello, 小明!
    

    比较两个Student

    这里new 出来的 Student 的 Hello 方法不是复用! 用其他语言的角度来看同一个类new出来的对象居然各自持有方法,真的是 泥垢了

    xiaoming.hello === xiaohong.hello;//false
    

    重写Student的构造函数

    function Student(name) {
        this.name = name;
    }
    
    Student.prototype.bioName = "智人";
    
    Student.prototype.hello = function () {
        alert('Hello, ' + this.name + '!');
    };
    
    var xiaoming = new Student('小明');
    var xiaohong = new Student('小红');
    
    //这里可以看出复用方法了 公用的东西应该放到 prototype 里面
    xiaoming.hello === xiaohong.hello;// true  
    xiaoming.bioName === xiaohong.bioName; //true
    
    
    
    xiaoming.bioName; //"智人"
    xiaohong.bioName; //"智人"
    
    xiaoming.bioName = "尼安德特人"
    xiaoming.bioName; //"尼安德特人"
    xiaohong.bioName; //"智人"  震惊了 这个bioName 不是共享的 按照道理来说应该是共用 prototype 的一个属性的那?
    
    xiaoming.bioName === xiaohong.bioName; //false 这里居然显示出来结果
    
    xiaoming.hasOwnProperty("name")// true
    xiaoming.hasOwnProperty("bioName")// true  !!! 看来是 小名赋值之后给自己天降了个 bioName  
    
    xiaoming;
    Student.prototype;
    //果然可以看出 prototype 里面的 bioName 依然是"智人",而xiaoming是新增bioName属性
    
    

    原型继承

    
    function Student(props) {
        this.name = props.name || 'Unnamed';
    }
    
    Student.prototype.hello = function () {
        alert('Hello, ' + this.name + '!');
    }
    
    //首先在构造函数中相互调用
    function PrimaryStudent(props) {
        // 调用Student构造函数,绑定this变量:
        Student.call(this, props);
        this.grade = props.grade || 1;
    }
    
    

    这个时候对于PrimaryStudent 原型链条是,看上去和Student没啥关系

    var Reimu = new PrimaryStudent({name :"Reimu"});
    
    QQ20161028-0.png

    new PrimaryStudent() ----> PrimaryStudent.prototype ----> Object.prototype ----> null

     Student.prototype
    
    QQ20161028-4.png
    PrimaryStudent.prototype
    
    QQ20161028-5.png

    这个两个家伙各自指向自家


    接下来就像是链表插值这类东西的

    QQ20161028-6.png

    来一个空函数F 桥接用 我们最终想实现下面这样的效果

    大象塞冰箱分三步 我们狸猫换太子 也走三步 搭四根线

    function F() {
    }
    
    QQ20161028-1.png
    // 把F的原型指向Student.prototype:  这里看上去是一步实际上搭上了两根线
    // F ->  原型对象
    // F ->  原型对象
    F.prototype = Student.prototype;
    
    
    QQ20161028-2.png
    // 把PrimaryStudent的原型指向一个新的F对象,F对象的原型正好指向Student.prototype:
    搭一根线   PrimaryStudent -> new F()
    PrimaryStudent.prototype = new F();
    
    QQ20161028-3.png
    // 把PrimaryStudent原型的构造函数修复为PrimaryStudent:
    搭上最后一根线
    new F() -> PrimaryStudent
    PrimaryStudent.prototype.constructor = PrimaryStudent;
    

    四根线搭上 原来 PrimaryStudent.prototype 指向的 无名原型对象已经被彻底的抛弃了 new F() 已经上位了,取代了无名 原型对象

    function inherits(Child, Parent) {
        var F = function () {};
        F.prototype = Parent.prototype;
        Child.prototype = new F();
        Child.prototype.constructor = Child;
    }
    

    就这样JavaScript终于打肿脸充胖子一样的实现了继承

    相关文章

      网友评论

          本文标题:JavaScript继承指迷

          本文链接:https://www.haomeiwen.com/subject/ezmeuttx.html