• 更适用于JavaScript的设计模式:面向委托的设计,了解一下?(下)


    先来看一下传统的面向类式的写法:

    function Foo(name) {
        this.name = name;
    }
    
    Foo.prototype.sayName = function() {
        console.log('name: ' + this.name)
    }
    
    function Bar(name, age) {
        Foo.call(this, name);
        this.age = age;
    }
    
    Bar.prototype = Object.create(Foo.prototype);
    
    Bar.prototype.sayAge = function() {
        console.log('age: ' + this.age)
    }
    
    
    var bar1 = new Bar('bar1', 13);
    
    bar1.sayName();
    bar1.sayAge();
    

    这里的Object.create也可以替换成Object.setPrototypeOf,但是我们这里并不care它的constructor指向是否正确,所以从可读性的角度我们用Object.create。(why ? 请参考上一篇)

    上面是传统的,也是最为推崇的寄生组合式继承模式,但是es6诞生以后,这种写法就不再流行了,更多的是利用class的语法糖,我们来看代码:

    class Foo {
        constructor(name) {
            this.name = name;
        }
        sayName() {
            console.log('name: ' + this.name);
        }
    }
    
    class Bar extends Foo {
        constructor(name, age) {
            super(name);
            this.age = age;
        }
        sayAge() {
            console.log('age: ' + this.age);
        }
    }
    
    var bar3 = new Bar('bar3', 15);
    
    bar3.sayName();
    bar3.sayAge();
    

    class的语法优势在于没有了prototype的混乱,很轻松地实现继承,利用super方法轻松实现构造函数的复制,等同于传统的call所实现的效果,extends实现委托机制,等同于Object.create所实现的效果。

    但是缺陷在于加深了人们对于类以及继承的误解。

    我们再来看利用委托的设计模式:

    Foo = {
        init(name) {
            this.name = name
        },
        sayName() {
            console.log('name: ' + this.name);
        }
    }
    
    Bar = Object.create(Foo);
    
    Bar.inits = function(name, age) {
        Foo.init.call(this, name);
        this.age = age;
    }
    
    Bar.sayAge = function() {
        console.log('age: ' + this.age);
    }
    
    var bar = Object.create(Bar);
    
    bar.inits('bar', 14);
    
    bar.sayName();
    bar.sayAge();
    

    同样,这里没有prototype的出现,也没有new构造函数调用,完全依靠委托的机制,完全是对象之间的联系。这种设计模式要求我们不再利用多态去重写原有的函数或属性,而是用不同的函数名或属性名消除这种歧义。

    可能存在的缺陷是之前的new构造函数被分成了两段代码。

    var bar = Object.create(Bar);
    
    bar.inits('bar', 14);

    但是有一个好处在于我们可以关注点分离,使得创建和初始化分离。

    以上三种是目前主流的实现仿类以及继承的范式,第二种目前相对较为流行,第三种更生僻一些,但是却最符合JavaScript的设计思想,没有类的概念,没有构造函数,只有对象与对象的联系,行为委托。并不强求一定要用哪一种,还是看个人喜好吧,因为很难讲三者的优胜好坏。

    end

  • 相关阅读:
    3、通道(中)
    2、通道(上-扣婚纱)
    1、色阶
    第三章—15、音乐播放界面效果
    第三章—14、下拉菜单
    第三章—13、点击按钮显示隐藏图片
    第三章-12、按钮的六种状态
    第三章—11、滑动导航(点击哪个就字体跟着变颜色)
    第三章-10、滑动选项卡(上)
    iOS 生命周期
  • 原文地址:https://www.cnblogs.com/yanchenyu/p/10275601.html
Copyright © 2020-2023  润新知