javascript设计模式-面向对象基础

这篇具有很好参考价值的文章主要介绍了javascript设计模式-面向对象基础。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、接口

在JS这种弱类型的语言中,类型不匹配错误很难跟踪。可以使用接口来进行类型检查。如果强制使用,又会弱化语言的灵活性。因为有额外的代码调用,所以又会降低性能。解决方法就是在开发时进行类型检查,在开始完成后删除此部分代码。

但JS中的接口实现方式是模拟的,它以文档和方法检查相结合。缺点在于它只检查方法的名称,并不检查参数的名称,类型,数量以及方法的返回值。

接口定义工具类

var Interface = function(name, methods) {
    if(arguments.length != 2) {
        throw new Error("Interface constructor expected exactly 2.");
    }
    this.name = name;//接口名称
    this.methods = [];//接口的方法名称数组
    for(var i = 0, len = methods.length; i < len; i++) {
        if(typeof methods[i] !== 'string') {
            throw new Error("Interface constructor expects method names is String.");
        }
        this.methods.push(methods[i]);
    }
};

Interface.ensureImplements = function(object) {
    if(arguments.length < 2) {
        throw new Error("Interface.ensureImplements exactly arguments at least 2.");
    }
    for(var i = 1, len = arguments.length; i < len; i++) {
        var interface = arguments[i];
        if(interface.constructor !== Interface) {
            throw new Error(interface + "exactly type is Interface.");
        }
        for(var j = 0, methodsLen = interface.methods.length; j < methodsLen; j++) {
            var method = interface.methods[j];
            if(!object[method] || typeof object[method] !== 'function') {
                throw new Error("Function Interface.ensureImplements: object "
                + "does not implement the " + interface.name
                + " interface. Method " + method + " was not found.");
            }
        }
    }
};
//模拟使用
//定义了接口Person0和Person1,并在每个接口中定义三个方法
var Interface0 = new Interface('Person0', ['add', 'del', 'getItem']);
var Interface1 = new Interface('Person1', ['add', 'del', 'getItem']);
function addForm(myClassInstance){
    //用来检查myClassInstance是否实现了接口Interface0和Interface1
    Interface.ensureImplements(myClassInstance, Interface0, Interface1)
}

JS的灵活性是其最大的特点,所以在强制类型检查时需要有选择的使用。

二、封装和信息隐藏

创建私有成员是OOP中最基本和有用的特性之一。信息隐藏是目的,封装则是达到这个目的的技术。JS实现封装的方式多种多样,比如公用、私用、特权。下面有两个简单的例子。

私有属性、方法、静态方法

Book.getInt8 = function(){
    //static Method
}
Book.prototype = {
    _checkIsbn: function (isbn) {
    }//用「-」人为约定私有方法和属性,并不在程序中提供保护
}

//用闭包的方式来实现私有方法和变量
var Book = function(newIsbn, newTitle, newAuthor) {
    // Private attributes.
    var isbn, title, author;
    // Private method.
    function checkIsbn(isbn) {
    }
}

常量

var Class = (function() {
    // Private static attributes.
    var constants = {
        UPPER_BOUND: 100,
        LOWER_BOUND: -100
    }
    //Constructor
    var ctor = function(constructorArgument){};
    // Privileged static method.
    ctor.getConstant = function(name){
        return constants[name];
    }
    // Return the constructor.
    return ctor;
})();
/* 调用,如果在上面的括号中加入参数也可以实现常量的动态实例化 */
var t = Class.getConstant('UPPER_BOUND');

三、继承

在实现JS继承时需要注意一个类依赖另一个类的内部实现这样的耦合关系。如果设计的是一个供众人使用的API,最好使用类继承方式。原型的方式更简洁也更节省内存。掺元适合即要共享类的方法又不需要结对的情况。

类式继承

//superClass
function Person(name) {
    this.name = name;
}
Person.prototype.getName = function() {return this.name;}

//subClass
function Author(name, books) {
    Person.call(this, name); //在子类中调用父类的构造.
    this.books = books; // Add an attribute to Author.
}

Author.prototype = new Person(); // Set up the prototype chain.
Author.prototype.constructor = Author; // Set the constructor
Author.prototype.getBooks = function() { // Add method to Author.
    return this.books;
};
function Person(name){
    this.name = name;
}
Person.prototype.getName = function() {
    return this.name;
};

function Author(name, books) {
    Author.superclass.constructor.call(this, name);
    this.books = books;
}
extend(Author, Person);
Author.prototype.getName = function() {
    var name = Author.superclass.getName.call(this);
    return name + ', Author of ' + this.getBooks().join(', ');
};

/* Extend function, improved.这处可以用JQUERY的EXTEND方法,比这个更好 */
function extend(subClass, superClass) {
    var F = function() {};
    F.prototype = superClass.prototype;
    subClass.prototype = new F();
    subClass.prototype.constructor = subClass;

    subClass.superclass = superClass.prototype;
    if(superClass.prototype.constructor == Object.prototype.constructor) {
        superClass.prototype.constructor = superClass;
    }
}

原型式继承

采用这种方式时,并不需要用类定义对象的结构,只需直接创建一个对象即可。这个对象随后可以被新的对象重用。这种方式可以看出,不需要定义子类的结构。代码更简洁,但也有优缺点,需要了解原型的实现方式。

function clone(object) {
    function F() {}
    F.prototype = object;
    return new F;
}
var Person = {
    name: 'default name',
    getName: function() {
        return this.name;
    }
};
var reader = clone(Person);

如果原型中还有自己的子对象时,需要修改子对象的默认值时,最好采用工厂的创建方法。

var CompoundObject = {};
CompoundObject.string1 = 'default value',
    CompoundObject.createChildObject = function() {
        return {
            bool: true,
            num: 10
        }
    };
CompoundObject.childObject = CompoundObject.createChildObject();

var compoundObjectClone = clone(CompoundObject);
compoundObjectClone.childObject = CompoundObject.createChildObject();
compoundObjectClone.childObject.num = 5;

掺元

/*使receivingClass类具有givingClass类的所有方法*/
function augment(receivingClass, givingClass) {
    for(methodName in givingClass.prototype) {
        if(!receivingClass.prototype[methodName]) {
            receivingClass.prototype[methodName] = givingClass.prototype[methodName];
        }
    }
}
/* 使receivingClass类具有givingClass类的特定方法. */
function augment(receivingClass, givingClass) {
    if(arguments[2]) { // Only give certain methods.
        for(var i = 2, len = arguments.length; i < len; i++) {
            receivingClass.prototype[arguments[i]] = givingClass.prototype[arguments[i]];
        }
    }
    else { // Give all methods.
        for(methodName in givingClass.prototype) {
            if(!receivingClass.prototype[methodName]) {
                receivingClass.prototype[methodName] = givingClass.prototype[methodName];
            }
        }
    }
}
//使类Author具有类BaseClass的SeriMethod方法
augment(Author, BaseClass, 'SeriMethod')

var Mixin = function() {};
Mixin.prototype = {
    serialize: function() {
    }
};

augment(Author, Mixin);//Author的代码省略了
augment(Author, Mixin, 'serialize');

var author = new Author('Ross Harmes', ['JavaScript Design Patterns']);
var serializedString = author.serialize();

四、方法的链式调用

定义一个构造函数,把元素作为数组保存在一个实例属性中,并让所有定义在构造函数的prototype属性所指对象中的方法都返回用以调用方法的那个实例的引用,那么就具有了进行链式调用的能力。

(function() {
  function _$(els) {
  }
  _$.prototype = {
    each: function(fn) {
      for ( var i = 0, len = this.elements.length; i < len; ++i ) {
        fn.call(this, this.elements[i]);
      }
      return this;
    },
    setStyle: function(prop, val) {
      this.each(function(el) {
        el.style[prop] = val;
      });
      return this;
    }
  };
  window.$ = function() {
    return new _$(arguments);
  };
})();

$(window).addEvent('load', function() {
  $('test-1', 'test-2').setStyle('color', 'red')
      .addEvent('click', function(e) {
      $(this).setStyle('color', 'green');
    });
});

五、构建一个简单的JS库框架

Function.prototype.method = function(name, fn) {
    this.prototype[name] = fn;
    return this;//指向_$
};
(function() {
    function _$(els) {
    }
    _$.prototype = {
        each: function(fn) {
            for ( var i = 0, len = this.elements.length; i < len; ++i ) {
                fn.call(this, this.elements[i]);
            }
            return this;
        },
        setStyle: function(prop, val) {
            this.each(function(el) {
                el.style[prop] = val;
            });
            return this;
        }
    };
    _$.method('show', function(){//扩展方法,这样就不必全写在原型中了
        return this;
    });
    window.installHelper = function(scope, interface) {
        scope[interface] = function() {
            return new _$(arguments);
        }
    };
})();
//定义此方法是防止$被占用
installHelper(window, '$');
var t = $('example').setStyle('color', 'green').show();//链式调用

链式调用很适合赋值操作,有时对于取值器方法,并不希望返回this,而是需要返回需要的数据,但如果不返回this就失去了链式调用的方便,所以这时可以使用callback Function。的方式。文章来源地址https://www.toymoban.com/news/detail-802507.html

window.API2 = window.API2 ||function(){
    var name='ld';
    this.setName = function(nn){
        name = nn;
        return this;
    };
    this.getName = function(cl){
        cl.call(this, name);//此处相当于一个return
        return this;
    }
};
var o2 = new API2;
o2.getName(a).setName('Meow').getName(a);
function a(a){
    console.log(a);
}

到了这里,关于javascript设计模式-面向对象基础的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 《设计模式的艺术》笔记 - 面向对象设计原则

    1、单一职责原则         一个类只负责单一功能领域中的相应职责。 2、开闭原则         一个软件实体应当对扩展开放,对修改关闭。即软件实体应当尽量在不修改原有代码的情况下进行扩展。 3、里氏代换原则         所有引用基类的地方必须能透明地使用其子类的对

    2024年01月21日
    浏览(14)
  • javaScript---设计模式-设计模式概论

    (1)帮助我们组织模块(2)帮助我们设计沟通(3)提高代码质量 开闭原则:对扩展开放,对修改关闭 单一职责原则:一个模块只做一件事情 依赖倒置原则:上层模块不要依赖具体的下层模块,而应该依赖于抽象 接口隔离原则:接口功能单一,能力单一,细化接口,接口功

    2024年02月03日
    浏览(27)
  • 设计模式学习笔记 - 面向对象 - 1.面向对象到底讨论的是什么

    面向对象编程( OOP )的全称是 Object Oriented Programming 。 面向对象编程语言( OOPL )的全称是 Object Oriented Programming Language 。 面向对象编程中有两个非常重要的概念,就是类( Class )和对象( Object )。面向对象编程这个概念第一次使用是在 SmallTalk 这种编程语言中,它也被认

    2024年02月22日
    浏览(13)
  • C++设计模式_02_面向对象设计原则

    变化是复用的天敌!面向对象设计或者说使用了抽象原则的面向对象设计最大的优势在于#

    2024年02月11日
    浏览(12)
  • 设计模式学习笔记 - 面向对象 - 3.面向对象比面向过程有哪些优势?面向过程真的过时了吗?

    在过往的工作中,我发现很多人搞不清面向对象和面向过程的区别,总认为使用面向对象编程语言来开发,就是在面向面向对象编程了。而实际上,他们只是在用面向对象编程语言,编写面向过程风格的代码而已,并没有发挥面向对象编程的优势。这就相当于手握一把屠龙刀

    2024年02月22日
    浏览(11)
  • JavaScript 设计模式之组合模式

    JavaScript 设计模式之组合模式

    在我们日常中肯呢个会将一个表单用这种模式来创建 先写一个基类,再继承该基类 首先我们创建一个基类 定义 接下来创建一个容器 注意,这里的 show 方法就是用来将所有的 dom 追加到页面上 下面创建一系列的 form 相关 item 及一些dom 使用  假使页面中存在 dom  js 效果 组合模

    2024年02月22日
    浏览(13)
  • JavaScript 设计模式之代理模式

    其实这种模式在现在很多地方也都有使用到,如 Vue3 中的数据相应原理就是使用的 es6 中的 Proxy 代理及 Reflect 反射的方式来处理数据响应式 我们日常在使用数据请求时,也会用到一些代理的方式,比如在请求不同的域名,端口等会出现跨域的情况,这时就需要用到代理去获

    2024年02月19日
    浏览(10)
  • JavaScript 设计模式之外观模式

    我们为啥要使用外观模式呢,其实我们在使用各种 js 库的时候常常会看到很多的外观者模式,也正是这些库的大量使用,所以使得兼容性更广泛,通过外观者模式来封装多个功能,简化底层操作方法 在我们写方法时,通常会传递参数的形式来传递数据 但是我们更应该这样来

    2024年02月20日
    浏览(13)
  • C++中的面向对象设计模式实践

    面向对象程序设计(Object-Oriented Programming,简称OOP)是一种将程序设计问题分解为对象的思维方式。它通过定义对象和对象之间的关系,将问题模型化并转化为代码实现。在面向对象设计模式中,设计模式是一种被普遍接受的解决问题的方法论。 C++作为一种多范式编程语言,

    2024年01月17日
    浏览(10)
  • JavaScript设计模式详解

    JavaScript设计模式是解决软件设计中常见问题的可重复使用的解决方案。本博客将深入探讨JavaScript设计模式的各个方面,包括设计模式的类别、创建型、结构型、行为型、并发型和架构型设计模式。 设计模式是一种在软件设计中解决常见问题的可重用解决方案。它们是经过验

    2024年01月19日
    浏览(11)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包