• JavaScript语言精粹 笔记03 继承


    继承
    伪类
    对象说明符
    原型
    函数化
    部件

    继承

    JS不是基于类的,而是基于原型的,这意味着对象直接从其他对象继承。

    1 伪类

    JS提供了一套丰富的代码重用模式,它可以模拟那些基于类的模式,因为JS实际上没有类,所以把模拟的类称为伪类。
    我们可以定义一个构造器并扩充它的原型:

    var Mammal = function (name) {
        this.name = name;
    };
    Mammal.prototype.get_name = function ( ) {
        return this.name;
    };
    Mammal.prototype.says = function ( ) {
        return this.saying || '';
    };

    现在可以构造一个实例:

    var myMammal = new Mammal('Herb the Mammal');
    var name = myMammal.get_name( ); // 'Herb the Mammal'

    可以构造另一个伪类来继承Mammal:

    var Cat = function (name) {
        this.name = name;
        this.saying = 'meow';
    };
    // 替换Cat.prototype 为一个新的 Mammal 实例
    Cat.prototype = new Mammal( );
    // 扩充新原型对象,添加purr和get_name方法
    Cat.prototype.purr = function (n) {
        var i, s = '';
        for (i = 0; i < n; i += 1) {
            if (s) {
                s += '-';
            }
            s += 'r';
        }
        return s;
    };
    Cat.prototype.get_name = function ( ) {
        return this.says( ) + ' ' + this.name +' ' + this.says( );
    };
    var myCat = new Cat('Henrietta');
    var says = myCat.says( ); // 'meow'
    var purr = myCat.purr(5); // 'r-r-r-r-r'
    var name = myCat.get_name( ); // 'meow Henrietta meow'


    2 对象说明符

     有时候构造器要接受一大串的参数。这可能是令人烦恼的,因为要记住参数的顺序可能非常困难。例如:

    var myObject = maker(f,l,s,c);

    不如这么写:

    var myObject = maker({
        first:f,
        last:l,
        state:s,
        city:c
    });

    现在多个参数可以按任何顺序排列,如果构造器会聪明地使用默认值,一些参数可以忽略掉,并且代码也更容易阅读。


    3 原型

     在一个纯粹的原型模式中,我们会摒弃类,转而专注于对象。基于原型的继承相比基于类的继承在概念上更为简单:一个新对象可以继承一个旧对象的属性。可以构造一个有用对象,接着构造更多和那个对象相似的对象。

    用对象字面量构建一个有用的对象:

    var myMammal = {
        name : 'Herb the Mammal',
        get_name : function ( ) {
            return this.name;
        },
        says : function ( ) {
            return this.saying || '';
        }
    };

    为Object增加一个create方法,用来创建新的实例

    if (typeof Object.create !== 'function') {
        Object.create = function (o) {
            var F = function () {};
            F.prototype = o;
            return new F();
        };
    }

    定制一个新实例:

    var myCat = Object.create(myMammal);
    myCat.name = 'Henrietta';
    myCat.saying = 'meow';
    myCat.purr = function (n) {
        var i, s = '';
        for (i = 0; i < n; i += 1) {
            if (s) {
                s += '-';
            }
            s += 'r';
        }
        return s;
    };
    myCat.get_name = function ( ) {
        return this.says( ) + ' ' + this.name + ' ' + this.says( );
    };

    这是一种“差异化继承”。通过定制一个新的对象,我们指明了它与所基于的基本对象的区别。


    4 函数化

     函数化模式有很大的灵活性,能够更好的封装和隐藏信息。

    构造一个产生对象的函数,给它起的名字以一个小写字母开头,因为它并不需要使用new前缀。该函数包括4个步骤:

    • 1.它创建一个新对象。有很多的方法去构造一个对象。它可以构造一个对象字面量,或者它可以和new 前缀连用去调用一个构造函数,或者它可以使用Object.beget方法去构造一个已经存在的对象的新实例,或者它可以调用任意一个返回一个对象的函数。
    • 2.它选择性的定义私有实例变量和方法。这些就是函数中通过var语句定义的普通变量。
    • 3.它给这个新对象扩充方法。这些方法荣有特权去访问参数,以及第二步中通过var语句定义的变量。
    • 4.它返回一个新对象。

    如下是一个函数化构造器的伪代码:

    var constructor = function (spec, my) {
        var that, 其他私有实例变量;
        my = my || {};
      把共享的变量和函数添加到my中
        that = 一个新对象
      添加给that的特权方法
        return that;
    };


    5 部件

     可以从一套部件中组合出对象来。例如:构造一个能够添加简单事件处理特性到任何对象上的函数。它会给对象添加一个on方法、一个fire方法和一个私有的事件注册表对象:

    var eventuality = function (that) {
        var registry = {};
    
        that.fire = function (event) {
    
    // 在一个对象上触发一个事件。该事件可以是一个包含事件名称的字符串,或者是一个拥有包含事件名称的type属性的对象。
    //通过‘on’方法注册的事件处理程序中匹配事件名称的函数将被调用。
    var array, func, handler, i, type = typeof event === 'string' ? event : event.type; // 如果这个事件存在一组事件处理程序,那么就遍历它们并按顺序依次执行。 if (registry.hasOwnProperty(type)) { array = registry[type]; for (i = 0; i < array.length; i += 1) { handler = array[i]; //每个处理程序包含一个方法和一组可选参数。
    //如果该方法是一个字符串形式的名字,那么就寻找到该函数。
    func = handler.method; if (typeof func === 'string') { func = this[func]; } // 调用一个处理程序,如果该条目包含参数,那么传递它们过去。否则,传递该事件对象。 func.apply(this,handler.parameters || [event]); } } return this; }; that.on = function (type, method, parameters) { // 注册一个事件,构造一条处理程序条目,将它插入到处理程序数组中。
    // 如果这种类型的事件还不存在,就构建一个。
    var handler = { method: method, parameters: parameters }; if (registry.hasOwnProperty(type)) { registry[type].push(handler); } else { registry[type] = [handler]; } return this; }; return that; };

     我们可以在任何单独对象上调用eventuality,授予它事件处理方法。我们也可以赶在that被返回前在一个构造器函数中调用它。

    eventuality(that);

    用这种方式,一个构造器函数可以从一套部件中组装出对象来。

    参考:《JavaScript语言精粹》Douglas Crockford著    赵泽欣 鄢学鹍 译

    转载请注明出处:

    作者:JesseLZJ
    出处:http://jesselzj.cnblogs.com

  • 相关阅读:
    tensorflow 镜像
    TDD、BDD、DDD
    Node.js结合Selenium做Web自动化测试
    Selenium 对元素element的操作举例
    Selenium UI 举例 getCssValue
    《测之重器——自动化测试框架搭建指南》
    《Robot Framework自动化测试修炼宝典》道长
    SQLServer中round函数
    SQLServer中对时间和长度的处理
    SQLServer中获取所有数据库名、所有表名、所有字段名的SQL语句
  • 原文地址:https://www.cnblogs.com/jesselzj/p/4787809.html
Copyright © 2020-2023  润新知