前言:在此说明Javascript设计模式所讲内容和知识点来自双越老师(wangEditor富文本开源作者)的视频,内容通俗易懂,受益匪浅,结合自己的学习心得整理成笔记,与大家分享,愿在前端的道路上越走越远.....
从“写好代码”到“设计代码”的过程,不仅是技术的提升,更是编程思维的提升,而这其中最关键的就是设计模式,是否理解并掌握设计模式,也是衡量程序员能力的标准之一。
学习前提
使用过jquery类库
有ES6基础,用过node.js和npm
对vue、react有所了解
搭建开发环境
代码是基于ES6的,需要webpack和Babel进行转义
1、初始化npm环境
npm init 会出现提示,一直按回车,最后输入yes即可

image.png
2、安装webpack(当下流行的打包工具)
普通安装:npm install webpack webpack-cli --save-dev
淘宝镜像(http://npm.taobao.org/)安装:npm install webpack webpack-cli --save-dev --registry=https://registry.npm.taobao.org
3、安装webpack-dev-server(是webpack集成本地服务的一个环境,写完代码需要在本地预览,修改文件后可以自动刷新)
npm install webpack-dev-server html-webpack-plugin --save-dev
4、安装babel(解析ES6语法)
npm install babel-core babel-loader babel-polyfill babel-preset-es2015 babel-preset-latest babel-plugin-transform-decorators-legacy --save-dev
5、创建文件
文件目录结构

image.png
创建webpack.dev.config.js文件进行配置
// 引入 node.js path文件 const path = require('path')// require 网页模板插件const HtmlWebpackPlugin = require('html-webpack-plugin')module.exports = { // 入口文件
entry: './src/index.js', /*
出口文件
@param __dirname 当前目录
@param filename 目录文件名
*/
output: { path: __dirname, filename: './release/bundle.js' // release 文件夹运行时会自动创建
}, /*
plugins插件列表,是一个数组
@param HtmlWebpackPlugin html模板
*/
plugins: [ new HtmlWebpackPlugin({ template: './index.html' // 自动生成的bundle.js 会自动注入到index.html
})
], // 本地开发环境服务器
devServer: { // 需要获取文件,从本地release文件夹里面获取
contentBase: path.join(__dirname, "./release"), // 根目录
open: true, // 自动打开浏览器
port: 9000, // 端口
}, // 模块
module: { // 规定
rules: [{ // 检验js文件
test: /\.js?$/, // 忽略的文件
exclude: /(node_modules)/, // 进行babel处理
loader: 'babel-loader'
}]
}
}创建.babelrc文件
{ "presets": ["es2015", "latest"], "plugins": ["transform-decorators-legacy"]
}更改package.json文件(json文件里面不能添加注释)
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", // 运行webpack命令,将配置指向webpack.dev.config.js文件,生成开发模式--mode development
"dev": "webpack-dev-server --config ./webpack.dev.config.js --mode development"
},运行npm run build,自动生成release文件

image.png
运行npm run dev,自动打开浏览器

image.png
面向对象
概念
1、类,即模板,通过模板实例化很多对象,和es5的构造函数原理相同,里面放属性和方法
//1、创建一个人(People)的模板//2、人具有姓名(name),年龄(age)的属性//3、人可以执行动作吃饭(eat())、讲话(speak())等方法,方法里面执行逻辑操作//1、创建一个人(People)的模板class People { constructor(name, age) { //2、人具有姓名(name),年龄(age)的属性
this.name = name, this.age = age
} //3、人可以执行动作吃饭(eat())、讲话(speak())等方法,方法里面执行逻辑操作
eat() { console.log('this is eat')
}
speak() { console.log(this.name, this.age)
}
}2、对象(实例),通过类可以赋值给很多对象
// 1、创建一个叫zhang的对象// 2、因为人的constructor里面需要传参数,所以将zhang的姓名(name)和年龄(age)传进去// 3、zhang便有人(People)的方法,可以吃(eat()),可以说(speak())const zhang = new People('zhang', 20)console.log(zhang.eat()) // zhangeatconsole.log(zhang.speak()) // 20// 创建实例2const wang = new People('wang', 30)console.log(wang.eat())console.log(wang.speak())三要素:继承、封装、多态
1、继承,子类继承父类
父类
//1、创建一个人(People)的模板,相当于父类class People { constructor(name, age) { //2、人具有姓名(name),年龄(age)的属性
this.name = name, this.age = age
} //3、人可以执行动作吃饭(eat())、讲话(speak())等方法,方法里面执行逻辑操作
eat() { console.log(`${this.name}eat`)
}
speak() { console.log(`${this.age}`)
}
}子类(学生)
// 实现子类继承父类// 人分为好多种,比如学生、白领,通过extends继承人的属相和方法class Student extends People { constructor(name,age,schoolNum){ // 通过关键字super将name,age交给父类处理
super(name,age) // 自己处理学号
this.schoolNum = schoolNum
} // 因为是学生,具有学习的方法
study(){ console.log(`学号为${this.schoolNum}的学生学习`)
}
}// 创建实例(学生jialin)const jiaLin = new Student('jialin',20,20120102)// jialin具有学习的方法,同时也具有人(People)的吃饭(eat())方法和说话(speak())方法console.log(jiaLin.study())console.log(jiaLin.eat())console.log(jiaLin.speak())子类(白领)
// 创建白领这个类,继承人的属性和方法class whiteCollar extends People{ constructor(name,age,workNum){ // 通过关键字super将name,age交给父类构造函数处理
super(name,age) // 自己处理工号
this.workNum = workNum
} // 因为是白领,具有工作的方法
work(){ console.log(`工号号为${this.workNum}的人工作`)
}
}// 创建实例(白领mumu)const mumu = new whiteCollar('mumu',30,123)// mumu具有工作的方法,同时也具有人(People)的吃饭(eat())方法和说话(speak())方法console.log(mumu.work()) // 工号号为123的人工作console.log(mumu.eat())console.log(mumu.speak())通过以上案列可以知道子类(学生、白领)不仅继承(拥有)了父类(人People)的属性和方法,还有属于自己的方法(学习study、工作work),自己也可以定义属性和方法
总结
1、People 是父类,公共的,不仅仅服务于Student和whiteCollar
2、继承可将公共方法抽离出来,提高复用,减少冗余,这是软件设计最基础和最高效的方式
2、封装,数据的权限和保密。简单来说,将对象里面的某些属性和方法不想让别人看见,有一些是可以开放出去(javascript不是很明显,typescript[是js的超集]具有明显的特征,如public、private、protexted关键字)
public 完全开放
protectted 受保护的
private 私有的
演示的为typescript语法,代码可以在此运行http://www.typescriptlang.org/play/index.html
class People { // ts中的属性要先声明
name
// 默认的是public 相当于public age
age
// 定义protected 受保护的属性,只有自己或者子类可以访问
protected weigth
// 定义private 私有的属性,别人用不了
private girlFriend constructor(name, age) { this.name = name this.age = age // 给weigth赋值
this.weigth = 120
this.girlFriend = "zdy"
}
eat() { console.log(`${this.name}eat`)
}
}class Student extends People{
schoolNum
constructor(name,age,schoolNum) { super(name, age) this.schoolNum = schoolNum
}
getWeight() { // 获取weight,这个属性来自父类,对子类是开放的
console.log(this.weigth) // 这里获取不到 girlFriend,是父类私有的,不对外开放
}
}// 创建实例let mumu = new Student('mumu',20,201210)
mumu.getWeight() //120// console.log(mumu.girlFriend) 编译是会报错,因为girFriend是私有属性总结
1、减少耦合,不该外露的不外露
2、利于数据、接口的权限管理
3、es6目前不支持,一般认为_开头的属性是private,比如var _num = 20
3、多态,同一接口的不同实现,简单来讲就是父类定义一个接口,子类实现不同的功能
代码演示
class People{ constructor(name){ this.name = name
}
saySomething(){
}
} // a继承 People
class A extends People { constructor(name){ super(name)
}
saySomething(){
alert(`${this.name}`)
}
}// b继承 People
class B extends People { constructor(name){ super(name)
}
saySomething(){
alert(`${this.name}`)
}
} // a、b使用父类People的saySomething()方法,展示不一样的结果,此为多态
let a = new A('jialin')
alert(a.saySomething()) let b = new A('mumu')
alert(b.saySomething())总结
1、保持子类的开放性和灵活性
2、面向接口编程(不用管子类如何实现,就看父类有多少接口)
面向对象在前端实际应用
1、可以理解jquery就是个class
2、$('p')是jquery的一个实例
代码演示
class jQuery { constructor(selector) { // 获取数组的slice
let slice = Array.prototype.slice // 获取节点,利用slice.call将其结果返回给一个数组,因为可能是多个dom节点
let dom = slice.call(document.querySelectorAll(selector))
// 获取dom的长度
let len = dom ? dom.length : 0
// 进行循环
for (let i = 0; i < len; i++) { // 将dom的数组元素赋值给this也就是实例的元素,元素的k就是数组的k,0,1,2...
this[i] = dom[i]
} // 赋值数组的长度
this.length = len this.selector = selector || ''
}
append(node) { //...
}
addClass(name) { //...
}
html(data) { //...
} // 此处省略若干 API}// 入口window.$ = function(selector) { // 这里其实就是工厂模式
return new jQuery(selector)
}console.log($('p'))为什么使用面向对象
1、程序的执行离不开顺序、判断、循环操作,也就是将其结构化
2、面向对象就是将零散的数据结构化
3、对于计算机而言,结构化的才是最简单的
4、编程应该是 简单&抽象,简单的前提是抽象,抽象后才简单
关于抽象:抽取事物的共同特征就是抽取事物的本质特征,舍弃非本质的特征。所以抽象的过程也是一个裁剪的过程。在抽象时,同与不同,决定于从什么角度上来抽象。抽象的角度取决于分析问题的目的。
作者:jia林
链接:https://www.jianshu.com/p/2728597e6337




随时随地看视频