PS:由於全部的設計模式都是基於面向對象來完成的,因此在講解設計模式以前先來過一下面向對象都有哪些知識點html
搭建開發環境node
初始化npm環境webpack
下載安裝nodejs安裝便可,nodejs自帶npm管理包,而後使用下面命令檢查node和npm的版本程序員
建立項目的文件夾,而後再項目目錄下使用npm init --yes生成package.json文件web
安裝webpack和配置webpacktypescript
在項目目錄下,使用以下命令進行安裝npm
npm install --save-dev webpack
npm install --save-dev webpack-cli
安裝完成後項目中的package.json文件就有相關的配置json
在項目根目錄建立webpack.dev.config.js文件設計模式
module.exports = { entry: './src/index.js', //項目入口文件 output: { path: __dirname, // 當前目錄 filename: "./release/bundle.js" // 運行的時候本身會建立出來 } }
配置package.json的scripts對象,新增一個dev瀏覽器
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev": "webpack --config ./webpack.dev.config.js --mode development" },
mode development表示設置成開發者模式
而後執行那npm run dev
這樣咱們webpack就配置好了
安裝webpack-dev-server和html-webpack-plugin
npm install webpack-dev-server html-webpack-plugin --save-dev
在根目錄建立一個index.html
而後在webpack.dev.config.js文件配置html模板和啓動服務的配置
const path = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') module.exports = { entry: './src/index.js', //項目入口文件 output: { path: __dirname, // 當前目錄 filename: "./release/bundle.js" // 運行的時候本身會建立出來 }, plugins: [ new HtmlWebpackPlugin({ template: "./index.html" }) ], devServer: { contentBase: path.join(__dirname, './release'), // 配置本地執行環境的根目錄 open: true, //執行命令瀏覽器自動打開 port: 9000 } }
修改package.json的script下的dev
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev": "webpack-dev-server --config ./webpack.dev.config.js --mode development" },
而後再執行npm run dev
安裝babel,解析ES6
npm install babel-core babel-loader babel-polyfill babel-preset-es2015 babel-preset-latest --save-dev
在項目根目錄建立.babelrc文件
{ "presets": ["es2015", "latest"], "plugins": [] }
在dev.webpack.config.js文件中配置module
module: { rules: [{ test: /\.js?$/, exclude: /(node_modules)/, // 略過 loader: 'babel-loader' }] },
而後咱們使用ES6語法測試babel是否配置成功
class Person { constructor (name) { this.name = name } getName () { return this.name } } let p = new Person('jack') alert(p.getName())
運行顯示,已經正確執行index.js中的代碼了
什麼是面向對象
面向對象類的概念
class Person { constructor (name, age) { this.name = name this.age = age } getName () { return this.name } speak () { return `My name is ${this.name}, age${this.age}` } }
面向對象實例化對象
let p1 = new Person('jack', 23) let p2 = new Person('jack',32) alert(p1.getName()) alert(p2.speak())
面向對象之繼承
定義一我的的父類Person
// 父類Person class Person { constructor (name, age) { this.name = name this.age = age } getName () { return this.name } speak () { return `My name is ${this.name}, age${this.age}` } }
定義一個Student子類繼承父類Person
// 子類,學生 class Student extends Person{ constructor (name, age, number) { super(name, age) this.number = number } // 子類特有的方法 study () { return '我正在學習' } // 覆蓋父類的方法 speak() { return `My name is ${this.name}, age${this.age}, number${this.number}` } }
實例化子類Student
let s1 = new Student('小明', 11, '1234567890') let s2 = new Student('小光', 12, '0987654321') alert(s1.study()) alert(s2.speak())
Person類是公共的不單單服務於Student,繼承能夠將公共方法和屬性抽離出來,提升複用性,減小冗餘
面向對象之封裝
面向對象的封裝特性中有三個關鍵字須要理解的:public 徹底開發,protected 對子類開發,private只對本身開發(惋惜ES6中還不支持,可使用typescript來演示)
ES6還不支持,通常認爲_開頭的屬性是私有屬性(private)
// 父類Person class Person { name age protected weight // 定一個體重的屬性,子類能夠訪問 constructor (name, age, weight) { this.name = name this.age = age this.weight = weight } getName () { return this.name } speak () { return `My name is ${this.name}, age${this.age}, weight${this.weight}` } } // 子類,學生 class Student extends Person{ number private girlfriend // 私有屬性,只有Students能夠訪問 constructor (name, age, number, weight, girlfriend) { super(name, age, weight) this.number = number this.girlfriend = girlfriend } study () { return '我正在學習' } getWeight () { return `My weight is ${this.weight}` } getGirlfriend () { return `My girlfriend is ${this.girlfriend}` // girlfriend屬性是私有的,外面不能訪問,只能提供一個方法 } speak() { return `My name is ${this.name}, age${this.age}, number${this.number}` } } let s1 = new Student('小明', 11, '1234567890', 123, 'xialli') let s2 = new Student('小光', 12, '0987654321',123, 'xiaohong') alert(s1.getWeight()) alert(s2.getGirlfriend())
數據的權限和保密,不讓外部程序看見,只暴露一些方法供外部程序調用
面向對象之多態
同一接口不一樣實現
// 父類Person class Person { constructor (name, age) { this.name = name this.age = age } speak () { // 父類中的speak方法不寫具體的實現,由子類來覆蓋實現 } } // 子類,學生 class Student extends Person{ constructor (name, age, number) { super(name, age) this.number = number } // 覆蓋父類的方法 speak() { return `My name is ${this.name}, age${this.age}, number${this.number}` } } // 子類,學生 class Teacher extends Person{ constructor (name, age) { super(name, age) } // 覆蓋父類的方法 speak() { return `My name is ${this.name}, age${this.age}, I m Teacher` } } let s1 = new Student('小明', 11, '1234567890') alert(s1.speak()) let t1 = new Teacher('大明', 30) alert(t1.speak())
面向對象的應用案例
模擬Jquery的寫法,理解Jquery是如何用面向對象實現的
class jQuery { constructor(seletor) { let slice = Array.prototype.slice let dom = slice.call(document.querySelectorAll(seletor)) let len = dom ? dom.length : 0 for(let i = 0; i < len; i++){ this[i] = dom[i] } this.length = len this.seletor = seletor || '' } append(node){ } addClass(name){ } html(data){ } } window.$ = function (selector) { // 工廠模式 return new jQuery(selector) } // 測試代碼 var $p = $('p') console.log($p) console.log($p.addClass)
在index.html中添加幾個p標籤測試
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>JavaScript設計模式</title> </head> <body> <p>JavaScript設計模式1</p> <p>JavaScript設計模式2</p> <p>JavaScript設計模式3</p> </body> </html>
面向對象的總結
基本上咱們程序員寫的業務代碼都是這樣的一個狀況:程序執行—順序,判斷,循環——結構化
爲什麼使用面向對象,其實面向對象就是數據結構化,將世界萬物集合到對象中利於管理和封裝,複用
UML類圖
什麼是UML類圖:Unified Modeling Language 統一建模語言,UML能夠包含不少種圖,本系列種使用的是類圖
畫圖工具:MS Office visio(比較複雜的類圖) 和 processon(本系列種使用這種)
建立類圖的格式以下:
接下來咱們使用processon來畫一個People的類圖
根據這個UML類圖編寫代碼
class People { constructor (name ,age) { this.name = name this.age = age } eat () { alert(`${this.name} eat something`) } speak () { alert(`My name is ${this.name}, age:${this.age}`) } }
接下來來設計一個比較複雜一點的類,類之間有各類關係的
泛化:表示繼承,關聯:表示引用
class People { constructor (name ,house) { this.name = name this.age = house } saySomething () {} } class A extends People { constructor(name, house){ super(name, house) } saySomething () { alert('I am A') } } class B extends People{ constructor(name, house){ super(name, house) } saySomething () { alert('I am B') } } class House { constructor(city) { this.city = city } showCity () { alert(`house in ${this.city}`) } }
// 測試代碼 let aHouse = new House('深圳') let a = new A('a', aHouse) console.log(a) // a有房子 let b = new B('b') console.log(b) // b沒有房子