成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript設(shè)計模式(一)

dreamtecher / 2210人閱讀

摘要:聲明設(shè)計模式系列是來自設(shè)計模式與開發(fā)這本書的讀書筆記,會結(jié)合自身的理解和一些項目經(jīng)驗做筆記,原書作者曾探前言什么是設(shè)計模式,設(shè)計模式就是在某種場合下對某個問題的一種解決方案。

聲明: 【JavaScript設(shè)計模式】 系列 是來自《JavaScript設(shè)計模式與開發(fā)》這本書的讀書筆記,會結(jié)合自身的理解和一些項目經(jīng)驗做筆記,原書作者 曾探

前言

什么是設(shè)計模式,設(shè)計模式就是在某種場合下對某個問題的一種解決方案。說通俗一點就是給一段代碼起個名字而已,比如一個用玻璃做的能裝水的東西,給它起個名字叫水杯,
大家一提到水杯就知道什么對象,具有什么功能,這樣大家一想到要喝水就找個水杯這么個東西,滿足需求

一、面向?qū)ο蟮腏avaScript 1、動態(tài)類型語音

JavaScript是一門典型的動態(tài)類型語言。記住這一特性很重要,比如js有個數(shù)組類型Array,要是一個對象,這個對象具有l(wèi)ength屬性,還擁有slic,splice方法,那也可以將這個對象當(dāng)做數(shù)組來用。這完全是可以的,因為語言是動態(tài)的,我們可以面向接口編程,而不是面向?qū)崿F(xiàn)編程。

2、多態(tài)

也正因為js是動態(tài)類型語言,所以js本身具有多態(tài)的特性。
什么是多態(tài)呢:多態(tài)就是同一操作作用于不同對象,產(chǎn)生不同的結(jié)果
例子:

function fun(obj) {
    obj.log()
}
function Obj1() {

}
Obj1.prototype.log = function () {
    console.log("....Obj1......")
}
function Obj2() {

}
Obj2.prototype.log = function () {
    console.log("....Obj2......")
}
fun(new Obj1()) // ....Obj1......
fun(new Obj2()) // ....Obj2......

給函數(shù) fun 傳遞不同對象,能得到不同的結(jié)果
這要是在Java就要設(shè)計成子類繼承同一個父類,調(diào)用的時候向上轉(zhuǎn)型才能調(diào)用同一個父類方法得到不同結(jié)果,多麻煩呀
JavaScript是一門動態(tài)語言,既沒有檢查創(chuàng)建的對象類型,也沒有檢查傳遞的參數(shù)類型,所以實現(xiàn)
多態(tài)就變得尤為簡單,不必諸如向上轉(zhuǎn)型的技術(shù)來實現(xiàn)多態(tài)

3、封裝

JavaScript是沒有私有變量和共有變量或共有方法的,但它有個函數(shù)作用域,我們可以利用這一特性來滿足這一點
例子:

var fun2 = (function () {
    var _name = "my name is 田生"
    return {
        name: _name,
        pubFun: function () {
            console.log(".....pubFun.....")
        }
    }
})()
console.log(fun2.name)    // my name is 田生
console.log(fun2.pubFun()) //.....pubFun.....
4、JavaScript中的原型繼承

JavaScript的對象不是通過實例化得到的,而是通過克隆原型對象Object.prototype得到的。
所以經(jīng)常會預(yù)定一個面試題是,js 的 new 操作做了哪些工作?那你可以這樣回答,new 操作符是
執(zhí)行一個構(gòu)造函數(shù),函數(shù)里面克隆了 Object.prototype 對象,并把新對象附上屬性值返回出去。
例子:

function Obj() {
    this.name = "田生"
}
var o1 = new Obj()
console.log(o1.name) // 田生
// 相當(dāng)于
function CloneObj() {
    var obj = new Object() // 從 `Object.prototype` 克隆一個新對象
    obj.name = "田生"
    return obj
}
var o2 = CloneObj()
console.log(o2.name)  // 田生
5、JavaScript中的原型璉

如果對象無法響應(yīng)某個請求時,它會把這個請求委托給它的構(gòu)造器的原型prototype去執(zhí)行
例子:

function Obj() {
    this.name = "田生"
}
var o1 = new Obj()
console.log(o1.toString()) // [object Object]
console.log(o1)

上面例子克隆了個新的 對象Obj ,新對象沒有 toString 方法,所以在調(diào)用 toString 方法時,這個請求就會委托給他的原型對象 Objectprototype去執(zhí)行
那你可能會疑惑,對象 Obj對象 是怎么和 Objectprototype對象掛上鉤的呢?
你可以試著在Chrome瀏覽器的開發(fā)者模式中輸入上面代碼,試著打印 console.log(o1)
會發(fā)現(xiàn) Obj 有個 proto 的屬性指向了 Object對象,這就是它們連接的紐帶

二、this、call 和 apply 1、this

當(dāng)函數(shù)作為對象的方法調(diào)用時,this 指向改對象

例子:

var Obj = {
    name: "田生",
    fun: function () {
        console.log(this.name)  // this 指向改 對象
    }
}
Obj.fun()  //  田生

當(dāng)函數(shù)不作為對象的屬性被調(diào)用時,也就是常說的普通方法,此時this指向全局對象

var name = "田生....2"
function fun1() {
    console.log(this.name) // fun1 當(dāng)做普通函數(shù),this指向全局
    function fun2() {
        console.log(this.name)  // fun2 也當(dāng)做普通函數(shù),this指向全局
    }
    fun2() // "田生....2"
}
fun1() // "田生....2"

fun2 函數(shù)的this為什么也指向全局呢?有必要再強調(diào)一下,當(dāng)函數(shù)不作為對象的屬性被調(diào)用時,也就是常說的普通方法,此時this指向全局對象!
當(dāng)然在 ES6 strict 模式下 this為undefined

2、call 和 apply

首先要明確一點,JavaScript 的 Function 實際上是功能完整的對象。那對象就可以調(diào)用方法。
所以在看到下面的例子就不要疑惑:

function fun(para) {
}
fun.length
fun.apply(null, ["田生"])
fun.call(null, "田生")
fun.toString()

為什么一個函數(shù)有屬性呢,為什么一個函數(shù)居然可以調(diào)用另一個方法呢,因為JavaScript 的 Function 實際上是功能完整的對象啊,對象就有屬性和方法啊

(1)、call 和 apply 的區(qū)別

沒啥區(qū)別,就接受參數(shù)的方式不一樣而已,apply 接受的第二個參數(shù)是集合,call接受的參數(shù)不固定用逗號隔開。
但可以說 call 是包裝在 apply 的語法糖,內(nèi)部實現(xiàn)也是將參數(shù)轉(zhuǎn)數(shù)組的形式,所以某種意義上講
apply的效率高一點。

(2)、call 和 apply 的用途

改變this的指向:

function Obj() {
  this.name = "HI 田生~"
  function fun() {
      console.log(this.name) // undefined
  }
  fun()
}
new Obj()

上面小節(jié)也講了,fun 沒綁定到對象上,所以在這里被當(dāng)做普通函數(shù)使用,this指向全局對象,那咱們要
this.name正常輸出怎么辦:

// 方法一:傳統(tǒng)的 _this 傳遞
function Obj() {
  this.name = "HI 田生~"
  var _this = this
  function fun() {
      console.log(_this.name) // HI 田生~
  }
  fun()
}
new Obj()

// 方法二:借助 apply 或 call
function Obj() {
  this.name = "HI 田生~"
  function fun() {
      console.log(this.name) // HI 田生~
  }
  fun.apply(this)
}
new Obj()

哪種方法好用我就不多說了

借用其他對象方法

var arr = []
Array.prototype.push.apply(arr,[1, 2, 3])
console.log(arr)  // [1, 2, 3]
三、閉包和高階函數(shù) 1、閉包

閉包這個概論總是不好理解,你可以簡單的理解為 閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)
例子:

var func = function () {
    var a= 1
    return function () {
        a++
        console.log(a)
    }
}
var fun = func()
fun() // 2
fun() // 3
fun() // 4

變量 a 是函數(shù) func 的局部變量,外部函數(shù)或?qū)ο鬅o法訪問,但 func 內(nèi)部的匿名函數(shù)能訪問,那就這個匿名函數(shù)就是一個閉包 ,將閉包返回出去,相當(dāng)于將訪問權(quán)給了外部環(huán)境,外部環(huán)境就可以訪問一個函數(shù)的
局部變量了。

2、閉包的作用

上面第一小點順帶講了閉包能使外部環(huán)境訪問局部變量,是作用點之一。閉包還可以延續(xù)局部變量的壽命
例子:

// 方式1
var report = function (src) {
    var img = new Image()
    img.src = src
}
report("http://wwww.tiansheng.logo.png")

// 方式2
var report = (function () {
    var img
    return function (src) {
        img = new Image()
        img.src = src
    }
})()
report("http://wwww.tiansheng.logo.png")

利用方式1有可能圖片還沒加載完數(shù)據(jù)就丟失了,因為 report 方法執(zhí)行完局部變量就銷毀了,而方法2
利用閉包的方式延長了變量的壽命

3、高階函數(shù)

高階函數(shù)至少需要滿足以下條件之一:

函數(shù)可以作為參數(shù)傳遞

函數(shù)可以作為返回值輸出

我們經(jīng)常寫的帶有對調(diào)函數(shù)就是一個高階函數(shù)
例子:

/**
 * 高階函數(shù)
 * @param name
 * @param callBack
 */
function fun(name, callBack) {
    // do something ...
    callBack()
}

函數(shù)作為返回值輸出,其實就是一種閉包的表現(xiàn)
下面一個單例模式的例子:

var getSingle = function (fn) {
    var ret;
    return function () {
        return ret || (ret = fn.apply(this, arguments))
    }
}

var getScript = getSingle(function () {
    // ...
})
var script1 = getScript()
var script2 = getScript()
console.log(script1 === script2) // true
小結(jié):

本小結(jié)寫了 【面向?qū)ο蟮腏avaScript】、【this、call 和 apply】、 【閉包和高階函數(shù)】 ,為接下去的JavaScript 設(shè)計模式做鋪墊

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/88725.html

相關(guān)文章

  • JS程序

    摘要:設(shè)計模式是以面向?qū)ο缶幊虨榛A(chǔ)的,的面向?qū)ο缶幊毯蛡鹘y(tǒng)的的面向?qū)ο缶幊逃行┎顒e,這讓我一開始接觸的時候感到十分痛苦,但是這只能靠自己慢慢積累慢慢思考。想繼續(xù)了解設(shè)計模式必須要先搞懂面向?qū)ο缶幊?,否則只會讓你自己更痛苦。 JavaScript 中的構(gòu)造函數(shù) 學(xué)習(xí)總結(jié)。知識只有分享才有存在的意義。 是時候替換你的 for 循環(huán)大法了~ 《小分享》JavaScript中數(shù)組的那些迭代方法~ ...

    melody_lql 評論0 收藏0
  • 理解JavaScript的核心知識點:原型

    摘要:首先,需要來理清一些基礎(chǔ)的計算機編程概念編程哲學(xué)與設(shè)計模式計算機編程理念源自于對現(xiàn)實抽象的哲學(xué)思考,面向?qū)ο缶幊淌瞧湟环N思維方式,與它并駕齊驅(qū)的是另外兩種思路過程式和函數(shù)式編程。 JavaScript 中的原型機制一直以來都被眾多開發(fā)者(包括本人)低估甚至忽視了,這是因為絕大多數(shù)人沒有想要深刻理解這個機制的內(nèi)涵,以及越來越多的開發(fā)者缺乏計算機編程相關(guān)的基礎(chǔ)知識。對于這樣的開發(fā)者來說 J...

    iKcamp 評論0 收藏0
  • 深入理解JavaScript

    摘要:深入之繼承的多種方式和優(yōu)缺點深入系列第十五篇,講解各種繼承方式和優(yōu)缺點。對于解釋型語言例如來說,通過詞法分析語法分析語法樹,就可以開始解釋執(zhí)行了。 JavaScript深入之繼承的多種方式和優(yōu)缺點 JavaScript深入系列第十五篇,講解JavaScript各種繼承方式和優(yōu)缺點。 寫在前面 本文講解JavaScript各種繼承方式和優(yōu)缺點。 但是注意: 這篇文章更像是筆記,哎,再讓我...

    myeveryheart 評論0 收藏0
  • JavaScript系列(四) - 收藏集 - 掘金

    摘要:函數(shù)式編程前端掘金引言面向?qū)ο缶幊桃恢币詠矶际侵械闹鲗?dǎo)范式。函數(shù)式編程是一種強調(diào)減少對程序外部狀態(tài)產(chǎn)生改變的方式。 JavaScript 函數(shù)式編程 - 前端 - 掘金引言 面向?qū)ο缶幊桃恢币詠矶际荍avaScript中的主導(dǎo)范式。JavaScript作為一門多范式編程語言,然而,近幾年,函數(shù)式編程越來越多得受到開發(fā)者的青睞。函數(shù)式編程是一種強調(diào)減少對程序外部狀態(tài)產(chǎn)生改變的方式。因此,...

    cfanr 評論0 收藏0
  • JavaScript設(shè)計模式與開發(fā)實踐》 —— <閱讀小札·>

    摘要:閱讀小札一閱讀前自大學(xué)課上,就開始接觸設(shè)計模式,但對設(shè)計模式卻鮮有研究與實踐。第二部分是核心部分,由淺到深講解個設(shè)計模式。設(shè)計模式遵循的原則所有設(shè)計模式罪訓(xùn)的一條原則就是找出程序中變化的地方,并將變化封裝起來。 閱讀小札 · 閱讀前 自大學(xué)Java課上,就開始接觸設(shè)計模式,但對設(shè)計模式卻鮮有研究與實踐。最近向公司反映和游說技術(shù)提升,得以獲得公司提供購書機會,借此認真學(xué)習(xí)前端學(xué)習(xí)之路的...

    Yangder 評論0 收藏0
  • 前端練級攻略(第二部分)

    摘要:是文檔的一種表示結(jié)構(gòu)。這些任務(wù)大部分都是基于它。這個實踐的重點是把你在前端練級攻略第部分中學(xué)到的一些東西和結(jié)合起來。一旦你進入框架部分,你將更好地理解并使用它們。到目前為止,你一直在使用進行操作。它是在前端系統(tǒng)像今天這樣復(fù)雜之前編寫的。 本文是 前端練級攻略 第二部分,第一部分請看下面: 前端練級攻略(第一部分) 在第二部分,我們將重點學(xué)習(xí) JavaScript 作為一種獨立的語言,如...

    BWrong 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<