三个原则
写好JavaScript的三个原则:各司其责 组件封装 过程抽象
各司其责
HTML/CSS/JavaScript各司其责
- HTML -> Structural ; CSS -> Presentational ; JavaScript -> Behavioral
- 应当避免不必要的由JS直接操作样式
- 可以用class来表示状态
- 纯展示类交互应寻求零JS方案
下面是三个版本的例子:深浅色模式切换
组件封装
组件是指Web页面上抽出来的一个个包含模块(HTML)、样式(CSS)和功能(JS)的单元。好的组件具备封装性、正确性、扩展性、复用性。实现组件的步骤:结构设计、展现效果、行为设计,三次重构:插件化重构、模板化重构、抽象化重构。
- 结构设计:HTML
- 展现效果:CSS
- 行为设计:JS
- API(功能),API 设计应保证原子操作,职责单一,满足灵活性。
- Event(控制流),使用自定义事件来解耦。
- 模板化重构
- 将HTML模板化,更易于扩展
- 抽象化重构(组件框架)
- 将通用的组件模型抽象出来
下面是一个轮播图的案例
实现切换行为,设计API,选择与轮播,定义类实现API。
不是很灵活,于是提出插件化
- 插件化重构,即解耦
- 将控制元素抽取成插件
- 插件与组件之间通过依赖注入方式建立联系
在构造函数定义很多内容,定义原点与选择。
插件化的过程就是将控制元素给抽象成插件,在插件与组件中建立联系。
过程抽象
过程抽象是指用来处理局部细节控制的一些方法,是函数式编程思想的基础应用。操作次数限制 操作次数限制常用场景有
- 一些异步交互
- 一次性的HTTP请求
通过高阶函数,以函数作为参数,就能得到写出一个只执行一次或者限制次数的函数,例如下面Once()函数,这个函数的参数是一个函数fn,然后执行时会返回一个函数出去,在返回函数中间进行判断fn是否存在,如果存在则用实际参数执行fn,然后将fn=null这样下次就不会执行该函数。例如下面,我声明了一个show函数,其中求a+b的和,并且打印了字符串,在下面我讲这个函数赋值给foo=once(show),然后调用了三次foo(),控制台中只执行了一次。
function once(fn){
return function(...args){
if(fn){ //判断函数是否存在,如果存在则用实际参数调用它,然后把它置为空
const ret = fn.apply(this, args);// 用实际参数执行函数
fn = null;// 置空,下次就不会执行判断语句里面的内容就不会调用函数
return ret;// 把fn的结果返回出去
}
}
}
function show(a, b) {
let ans = a + b
console.log("打一下~");
return ans
}
let foo = once(show);
console.log(foo(10, 20));//"打一下~ 30
console.log(foo(30, 40));//undeifined
console.log(foo(50, 60));//undeifined
高阶函数
- 以函数做为参数
- 以函数作为返回值
- 常用于作为函数装饰器
节流函数的作用: 假设后台需要记录一个用户的行为,例如鼠标移动,但是用户会经常移动鼠标,即使用户稍微移动下,也会发送很多数据到后台去,这个就会造成很大的带宽浪费,用户移动的鼠标的数据不是说要完全的发送给后台去,我们可以设定一个间隔时间来记录一次数据就可以限制其数据。
节流函数的思路: 使用高级函数思路,以原始函数fn为参数,返回一个函数作为结果,我们会设置一个timer,如果这个timer没有的话就执行fn,同时会给这个timer注册一个setTimeout,在指定的时间后把timer=null,timer存在的时间内,无论怎么调用这个节流函数,因为timer不为空,所以都不会执行fn。
function throttle(fn, time = 500){
let timer;
return function(...args){
if(timer == null){ // 如果timer不为空则不进入判断体,就不会再次执行fn
fn.apply(this, args);
timer = setTimeout(() => {
timer = null;
}, time)
}
}
}
防抖函数的作用: 当记录鼠标移动的时候,如果我们一直胡乱移动鼠标,是不会记录鼠标,只有当鼠标停止的时候才会记录,例如下面的小鸟,当我们胡乱移动鼠标的时候,它并不会移动,只有当鼠标停止它才会移动过来
节流函数的思路: 仍然使用高级函数思路,依然用一个
timer来记录,每次移动的时候清除掉上一个timer定时器,然后又给这个timer重新注册一个setTimeout定时器,只有当定时器自动执行结束后才会执行fn
编程范式
编程范式: 包括JavaScript等很多现代脚本语言是混合的编程范式,编程范式是有几种分类的,大的分类分成命令式 和声明式。 命令式 又分成过程式和面向对象; 声明式 又分成逻辑式和函数式; JavaScript这种现代脚本语言是一种混合的编程范式,多少都既带有这种命令式,也带有声明式的特点,所以我们可以通过JS写出符合命令式 风格的代码, 也可以写出声明式风格的代码,命令式 和声明式 没有优劣之分。同时支持两种风格语言让JavaScript的写法更加灵活
总结
这堂课讲的知识非常的多而且杂,但总体分成三个原则写好JavaScript的三个原则:各司其责 组件封装 过程抽象,需要深入、清晰并结构化地阐述重点、经验和最佳实践。