资讯专栏INFORMATION COLUMN

JavaScript设计模式

dreambei / 244人阅读

摘要:此处的构造函数使用的形式添加新属性,但实际上新属性的添加有四种方式,除去这一种,还有三种方括号语法,方法方法此处举的是原文中的例子,若要使用,可参考原文。

参考书籍Learning Javascript Design Patterns

一、设计模式概述与应用场景

首先引用原书的一段话:

Patterns are proven solutions: They provide solid approaches to solving issues in software development using proven techniques that reflect the experience and insights the developers that helped define them bring to the pattern.

Patterns can be easily reused: A pattern usually reflects an out of the box solution that can be adapted to suit our own needs. This feature makes them quite robust.

Patterns can be expressive: When we look at a pattern there’s generally a set structure and vocabulary to the solution presented that can help express rather large solutions quite elegantly.

这里提到了三点:

设计模式是开发者定义的

设计模式必须具有可重用性,必须很好地处理各种异常情况

设计模式必须有自己的一套完整表述

光这样写可能既抽象又无趣,因而不妨从几个小点展开说一下。

设计模式在robustness(鲁棒性,我对这个翻译一直很不满)上的卓越表现,使得开发者可以省去一些花在代码结构组织上的经历,而更专于于业务逻辑开发,同时这也可以省去开发者日后重构代码的不便。

设计模式的通用性也是它的泛用性,它不局限于特定的使用环境,也不局限于特定的语言,你用C++,C#,Java,Python,JS都能写,语言是可以任选的。

同时好的设计模式也可以有效减小代码体积。

设计模式分为三大类:

创造型设计模式(creational design patterns)

结构型设计模式(structural design patterns)

表现型设计模式(behaviorial design patterns)

以下将主要说说第一类设计模式,之后两类可能会在以后的博客提及。

二、构造者模式

考虑一个最基本的JS对象构造函数:

function Car( model, year, miles ) {
 
  this.model = model;
  this.year = year;
  this.miles = miles;
 
  this.toString = function () {
    return this.model + " has done " + this.miles + " miles";
  };
}

当需要使用这个构造函数构造一个对象时,只要在函数调用之前加上new操作符,JS引擎将会识别出这是一个构造函数调用,这样,这个函数会默认返回一个this对象,这个对象的原型就是构造函数的prototype,因此,函数中对model,year等属性的赋值,就是对这个返回的对象进行的各种操作,使得我们能得到我们想要的对象。

此处的构造函数使用this.的形式添加新属性,但实际上新属性的添加有四种方式,除去这一种,还有三种:

方括号语法,newObject["someKey"] = "Hello World";

Object.defineProperty方法

Object.defineProperty( newObject, "someKey", {

value: "for more control of the property"s behavior",
writable: true,
enumerable: true,
configurable: true

});

Object.defineProperties方法

Object.defineProperties( newObject, {

"someKey": {

value: "Hello World",
writable: true

},

"anotherKey": {

value: "Foo bar",
writable: false

}

});

此处举的是原文中getter的例子,若要使用setter,可参考原文。

原文此处还提到了在构造函数的原型上定义公有方法的方式,这么做可以使得每次使用构造函数创建对象时不会重新创建一个属于被创建对象的方法,而是全部使用这个公有方法。

三、模块化模式

构造者模式的思想非常好,但是在一点上它有所欠缺,即私有变量。在Java中,声明私有变量可以采用private关键字,限制变量只能被一个类使用,它的后代,它实例化出来的对象都不能访问这个变量。

这是一种非常重要的编程思想,那么如果想用JS去实现应该怎么做呢?原文中举的例子以IIFE(立即执行函数)为主,为了与es6接轨,下面的例子将围绕es6的module展开。

首先介绍一下es6的module。为了处理日益增长的js文件造成的命名冲突和安全问题,ECMA引入了module,在module中声明的变量不会添加到全局作用域中,这样就可以避免全局污染,同时module可以指定需要输出的变量和方法。这里只举一个简单的导出与导入例子:

// export data
export var color = "red";
export let name = "Nicholas";
export const magicNumber = 7;

// export function
export function sum(num1, num2) {
    return num1 + num1;
}

// export class
export class Rectangle {
    constructor(length, width) {
        this.length = length;
        this.width = width;
    }
}

// this function is private to the module
function subtract(num1, num2) {
    return num1 - num2;
}

// define a function...
function multiply(num1, num2) {
    return num1 * num2;
}

// ...and then export it later
export { multiply };

代码来自nicolas zakas所著understanding es6中“用模块封装代码”一章,若对es6的模块化感兴趣,可阅读相关章节。

回到我们刚刚说的问题上来,为了实现“私有变量”这个概念,以上的代码中定义了一个substract方法,因为它没有被导出,所以此方法仅在此模块内可用,这样es6就从标准上实现了私有变量。

原文里详细描述了模块化模式,它主要包装了公有和私有方法,在上面的例子中,被导出的变量、常量、函数、类均可视为公有方法。模块化模式的思想就是导出一部分公有api,而维持在闭包之内的变量私密。

为了详细地说明这种思想,我们还是举一段原文的代码来做说明(es6的module同样可以实现类似的效果)

var testModule = (function () {
 
  var counter = 0;
 
  return {
 
    incrementCounter: function () {
      return counter++;
    },
 
    resetCounter: function () {
      console.log( "counter value prior to reset: " + counter );
      counter = 0;
    }
  };
 
})();

请关注这里的核心var counter = 0,这个私有变量是在导出的公有方法中进行操作的,用户获得的对象并没有办法直接操作这个私有变量。看到这里你可能会联想到闭包,没错,它们的思想是类似的。

模块化模式同样允许传入全局变量如$,并对它进行一些操作。

模块化也是有一些缺点的,最致命的就是私有变量不能被之后添加的方法操作,这对于debug而言绝对是一场噩梦。

了解模块化更多相关请狠狠戳这篇文章

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/107128.html

相关文章

  • JS程序

    摘要:设计模式是以面向对象编程为基础的,的面向对象编程和传统的的面向对象编程有些差别,这让我一开始接触的时候感到十分痛苦,但是这只能靠自己慢慢积累慢慢思考。想继续了解设计模式必须要先搞懂面向对象编程,否则只会让你自己更痛苦。 JavaScript 中的构造函数 学习总结。知识只有分享才有存在的意义。 是时候替换你的 for 循环大法了~ 《小分享》JavaScript中数组的那些迭代方法~ ...

    melody_lql 评论0 收藏0
  • 2017年 最好的javascript 书籍

    摘要:请记住,这些书中的一些可能不是最新的,但概念和基础仍应适用。是最好的老师之一。的秘密由部分组成。在你完成这些书后,查看书籍和最好的本土书籍。 我看过三本,第1本,第二本,第四本。第一本买的的实体书,其他两本看的是电子书。第一本是大名鼎鼎老道写的,书很薄,但是非常经典。javascirpt忍者秘籍是jquery的作者写的,也是非常经典。you dont kown js系列也是非常好。看了...

    mingzhong 评论0 收藏0
  • 前端练级攻略(第二部分)

    摘要:是文档的一种表示结构。这些任务大部分都是基于它。这个实践的重点是把你在前端练级攻略第部分中学到的一些东西和结合起来。一旦你进入框架部分,你将更好地理解并使用它们。到目前为止,你一直在使用进行操作。它是在前端系统像今天这样复杂之前编写的。 本文是 前端练级攻略 第二部分,第一部分请看下面: 前端练级攻略(第一部分) 在第二部分,我们将重点学习 JavaScript 作为一种独立的语言,如...

    BWrong 评论0 收藏0
  • 理解JavaScript的核心知识点:原型

    摘要:首先,需要来理清一些基础的计算机编程概念编程哲学与设计模式计算机编程理念源自于对现实抽象的哲学思考,面向对象编程是其一种思维方式,与它并驾齐驱的是另外两种思路过程式和函数式编程。 JavaScript 中的原型机制一直以来都被众多开发者(包括本人)低估甚至忽视了,这是因为绝大多数人没有想要深刻理解这个机制的内涵,以及越来越多的开发者缺乏计算机编程相关的基础知识。对于这样的开发者来说 J...

    iKcamp 评论0 收藏0
  • JavaScript系列(四) - 收藏集 - 掘金

    摘要:函数式编程前端掘金引言面向对象编程一直以来都是中的主导范式。函数式编程是一种强调减少对程序外部状态产生改变的方式。 JavaScript 函数式编程 - 前端 - 掘金引言 面向对象编程一直以来都是JavaScript中的主导范式。JavaScript作为一门多范式编程语言,然而,近几年,函数式编程越来越多得受到开发者的青睐。函数式编程是一种强调减少对程序外部状态产生改变的方式。因此,...

    cfanr 评论0 收藏0
  • JavaScript进阶之路

    摘要:前端入门的门槛相对较低,学习曲线是越来越陡峭,由浅入深,可以分为四个阶段。第二阶段高级程序设计有的书是用来成为经典的,比如犀牛书还有些书是用来超越经典的,显然这本书就是。接下来可以看看教程,看看源代码,尝试着写一写这些效果。 前端入门的门槛相对较低,学习曲线是越来越陡峭,由浅入深,可以分为四个阶段。 第一阶段:《JavaScript DOM编程艺术》    看这本书之前,请先确认你对J...

    Lowky 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<