• JavaScript的类和继承


    本文参考了两本书:

    <JavaScript: The Good Parts>(JSTGP) by Douglas Crockford

    <JavaScript Web Application> (JSWA) by maccman

    如何在JavaScript中使用”类“,W3CSHOOL提供了一个貌似不错的解决方案,也就是所谓的PseduoClassical范式:

    var Person = function (opt) {
    opt = opt ? opt : {};
    this.name = opt.name;
    };
    Person.prototype.hello = function() {
    console.log("hello, I'm " + this.name);
    };
     
    var Programmer = function (opt) {
    opt = opt ? opt : {};
    Person.apply(this, arguments);
    this.language = opt.language;
    };
    Programmer.prototype = new Person();
    Programmer.prototype.coding = function() {
    console.log("I'm coding with " + this.language);
    };
     
    var lucy = new Person({name: "lucy"});
    lucy.hello();
    var jack = new Programmer({name: "jack", language: "JavaScript"});
    jack.hello();
    jack.coding();

    一切都很熟悉,类有了,继承也很明朗。只是你可能感到疑惑,

    *为什么一个类要使用function关键字来定义呢?

    *这一句:Programmer.prototype = new Person(); 显得有些别扭,它是如何实现继承关系的?

    这是因为,new操作符实际上是JavaScript对面向对象程序员的一种妥协。它做的工作,就是,以Function的prototype为模板创建并返回一个新对象。在JSTGP的Function一章里,给出了如果new的方法实现版本:

    Function.prototype.new = function() {
        var that = Object.create(this.prototype);
        var object = this.apply(that, arguments);
        return (object && typeof object === 'object') ? object : that; //如果你用来定义“类”的function有返回值,那么返回该值,一般你不会这么做
    };
    ...
    var lucy = Person.new({name: "lucy"});

    为什么用function关键字来定义类呢?实际上初学者有一个误区,对prototype chain的误解,看看下面的代码:

    var lucy = Person.new({name: "lucy"});
    lucy.hello();
    var nobody = {};
    nobody.prototype = lucy;
    nobody.hello();

    TypeError: Object #<Object> has no method 'hello'

    这段代码的问题就是,认为prototype是对象的一个属性,设置了prototype之后,nobody的hello方法就会向上寻址。实际上,prototype是function的一个属性,而它的存在,只是为了上文提到的new操作的抽象。虽然可以说,JavaScript的new操作大致上像其他语言一样是按照模板来创建实例。但是一个显著的不同是,例如c#,一个新对象必须通过new创建,而JavaScript则不然,在上例中,是通过Object.create创建的,而new操作反而是一个语法糖(Sugar),另外,你也能够很容易的通过var a = {};这样的语句来创建一个对象。

    JavaScript是一种Prototype Based Language,而不是Class Based Language。本质区别是,Class Based Language的类是静态的,也就是说,一个对象的能力是静态的,而Prototype Based Language的对象的能力是动态的。可以说,JavaScript天然没有类,因而天然没有继承。而JSTGP更是指出,new是JavaScript设计中的缺陷,不要使用new。下面介绍Functional范式,在不使用new的情况下,提供对象模板:

    var person = function (name) {
        var that = {};
        that.sayHello = function () {
            console.log("Hello, my name is " + name);
        };
        return that;
    };
    
    var programmer = function (name, language) {
        var that = person(name);
        that.code = function () {
            console.log("I'm coding with " + language);
        };
        return that;
    };

    这种范式有一个好处,就是可以拥有私有成员,因为定义的方法可以访问函数作用域;而一个不好的地方就是,它的每个实例都会有自己的独立的方法,造成了内存的比较大的消耗。

     但是面向对象的概念有助于大型软件的开发,在下一篇文章里,我们将讨论一种巧妙的范式,在不使用别扭的new的情况下,提供明朗的类和继承。

  • 相关阅读:
    根据模板自动生成数据
    CSV to XLSX (专用)
    释放用完的Excel COM组件
    配置文件的力量
    字符编解码的故事(ASCII,ANSI,Unicode,Utf-8区别)
    将结果中的省略号内容全部输出
    Powershell变量的类型
    一些用过的C#类库收集
    运算符
    特殊运算符
  • 原文地址:https://www.cnblogs.com/zhengwenwei/p/2770412.html
Copyright © 2020-2023  润新知