1. UI层的松耦合

1.1 Web UI分层

bd12fd250945d6e9ce67d362c6b4a8e3d80c882ca9f21b4ee73eb635bfd64d90.png

1.2 将JavaScript从CSS中抽离

避免使用CSS表达式(expression函数)

1.3 将CSS从JavaScript中抽离

可以通过在JavaScript中操作CSS的className来达到修改元素样式的目的

1.4 将JavaScript从HTML中抽离

1.5 将HTML从JavaScript中抽离

1.5.1 从服务器加载

604fc6dcc64c3d26a7bc5cdeadc9f5d96474654297458d979d5916c5c1ea684c.png

1.5.2 简单客户端模板

1.5.3 复杂客户端模板

2. 避免使用全局变量

2.1 全局变量带来的问题

2.1.1 命名冲突

2.1.2 代码的脆弱性

2.1.3 难以测试

2.2 意外的全局变量

2.2.1 避免省略var关键字

2.2.2 避免意外的全局变量

2.2.3 如果可以使用严格模式(“use strict”)

2.3 单全局变量方式

2.3.1 命名空间

2.3.2 模块

YUI模块

异步模块(AMD)

2.4 零全局变量

3. 事件处理

3.1 隔离应用逻辑

3.2 不要分发事件对象

d3cb89f976b98345c00a4cf9474854ee269b2ba5400c8cfae412012d58ea5866.png

4. 避免”空比较”

4.1 检测基本类型

4.1.1 字符串

  1. typeof "hello"; // "string"

4.1.2 数字

  typeof 123;  // "number"

4.1.3 布尔

  typeof true;  // "boolean"

4.1.4 undefined

  typeof undefined;  // "undefined"

4.1.5 null

  typeof null;  // "object"
   这是一种低效的判断null的方法,如果你需要检测null,则直接使用恒等运算符(===)或非恒等运算符(!==)
  一般不用于检测语句

4.2 检测引用类型

4.2.1 instanceof

  • Date、Error、RegExp、自定义引用类型
  • 检测引用类型最好的方法是使用instanceof运算符
  • instanceof不仅检测构造这个对象的构造器,还检测原型链
  • 默认情况下,每个对象都继承自Object,因此每个对象的”value instanceof Object”都会返回true
  • 因此使用”value instanceof Object”来判断对象是否属于某个特定类型的做法并非最佳。

ddd85c37ec1d09fa1ebaeec7f1841874c7ff5b3d6f57a7480f484ca7560fbdaf.png

4.2.2 检测函数

  检测函数最好的方法是使用typeof,因为它可以跨帧(frame)使用<br />      typeof myFun === "function"(IE8+)<br />   ![971e2b3a7d30f922df9e1680184890f5e4e85584e93316fe816615f839121da8.png](https://cdn.nlark.com/yuque/0/2021/png/643343/1614867029784-93135d18-cd1a-47ae-b5e8-9e602f40690a.png#align=left&display=inline&height=55&margin=%5Bobject%20Object%5D&name=971e2b3a7d30f922df9e1680184890f5e4e85584e93316fe816615f839121da8.png&originHeight=55&originWidth=319&size=2494&status=done&style=none&width=319)

4.2.3 检测数组

  Array.isArray()<br />   ![f3efcd46eba3a89cecb2c2123fd4ac65907f386e9d73ed86f5e79c568883c117.png](https://cdn.nlark.com/yuque/0/2021/png/643343/1614867094846-58ce538f-c8ae-41d0-8b89-98ca8bc18233.png#align=left&display=inline&height=131&margin=%5Bobject%20Object%5D&name=f3efcd46eba3a89cecb2c2123fd4ac65907f386e9d73ed86f5e79c568883c117.png&originHeight=131&originWidth=525&size=5867&status=done&style=none&width=525)<br /> 

4.3 检测属性

4.3.1 判断属性是否存在的最好方法是使用in运算符

4.3.2 如需判断实例属性也可以用hasOwnProperty()

b883a8735cea464c893ed563cf773616a5bd7cfe574d8d8190881976d4860ae9.png

5. 将配置数据从代码中分离出来

5.1 什么是配置数据

5.1.1 URI

5.1.2 需要展现给用户的字符串

5.1.3 重复的值

5.1.4 设置(比如每页的配置项)

5.1.5 任何可能发生变更的值

5.2 抽离配置数据

5.3 保存配置数据

6.抛出自定义错误

6.1 错误的本质

抛出错误的本质是为了调试方便

6.2 在JavaScript中抛出错误

throw new Error(“Something bad happened.”)

6.3 抛出错误的好处

便于调试

6.4 何时抛出错误

  • 一旦修复了一个很难调试的错误,尝试增加一两个自定义错误。当再次发生错误时,这将有助于更容易的解决问题。
  • 如果正在编写代码,思考一下:”我希望[某些事情]不会发生,如果发生,我的代码会一团糟糕”。这时,如果[某些事情]发生,就抛出一个错误。
  • 如果正在编写的代码别人(不知道是谁)也会使用,思考一下他们使用的方式,在特定的情况下抛出错误。

    6.5 try-catch语句

    6.5.1 使用throw还是try-catch

    6.5.2 不要将try-catch中的catch留空

    6.6 错误类型

    6.6.1 Error

    所有错误的基本类型。实际上引擎从来不会抛出该类型错误

    6.6.2 EvalError

    通过eval()函数执行代码发生错误时抛出

    6.6.3 RangeError

    一个数字超出它的边界时抛出。该错误在正常的代码执行中非常罕见

    6.6.4 ReferenceError

    期望的对象不存在时抛出

    6.6.5 SyntaxError

    有语法错误时抛出

    6.6.6 TypeError

    变量不是期望的类型时抛出

    6.6.7 URIError

    给encodeURI(), encodeURIComponent(), decodeURI()或者decodeURIComponent()等函数传递格式非法的URI字符串时抛出

    7.不是你的对象不要动

    7.1 什么是你的

    在一个多人开发的项目中,每个人都假设库对象会按照它们的文档中描述的一样正常工作。如果你修改了其中的对象,将会给自己的团队设置一个陷阱。

    7.1.1 原生对象(Object、Array等等)

    7.1.2 DOM对象(document等)

    7.1.3 浏览器对象模型(BOM)对象(window等)

    7.1.4 类库的对象

    7.2 原则

    7.2.1 不覆盖方法

    以下代码会导致函数劫持
    dbcd7b64c487fcf5118b8cd5279ea94dbede2091b9ef4c7d02be469d5d1379d0.png

    7.2.2 不新增方法

    避免命名冲突

    一个对象此刻没有某个方法不代表它未来也没有

    7.2.3 不删除方法

    7.3 更好的途径

    7.3.1 基于对象的继承(原型继承)

    7.3.2 基于类型的继承

    7.3.3 门面模式

    7.4 关于Polyfill的注解

    7.5 阻止修改

    7.5.1 防止扩展

    禁止为对象“添加”属性和方法,但已存在的属性和方法是可以被修改和删除的
    9f51e794c39c8af7a89b8d7b220bc846c3e5fbc4572155d3539927f2123b5e73.png

    7.5.2 密封

    类似“防止扩展”,但是禁止”删除”对象已存在的属性和方法
    f728cadea6bc8fc43b6a5ffa4ab7cba618210c37a748d2a690088712f29cba07.png

    7.5.3 冻结

    类似“密封”,但是禁止”修改”对象已经存在的属性和方法
    870e5edf0ccd6906a46f94ff7922dbb4649aa4e7c820f412306b590c84395954.png

    8.浏览器嗅探

    8.1 User-Agent检测

    只针对旧的或者特定版本的浏览器,绝不应当针对最新版本或者未来版本的浏览器

    8.2 特性检测

    纯粹的特性检测是一种很好的做法

    8.3 避免特性推断

    应当不惜一切代价避免使用

    8.4 避免浏览器推断

    应当不惜一切代价避免使用