最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

js詞法作用域與this實(shí)例詳解

 更新時(shí)間:2022年09月05日 09:36:47   作者:hellomarker  
作用域值一個(gè)變量的作用餓范圍,下面這篇文章主要給大家介紹了關(guān)于js詞法作用域與this的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

靜態(tài)作用域又叫做詞法作用域,采用詞法作用域的變量叫詞法變量。詞法變量有一個(gè)在編譯時(shí)靜態(tài)確定的作用域。詞法變量的作用域可以是一個(gè)函數(shù)或一段代碼,該變量在這段代碼區(qū)域內(nèi)可見(visibility);在這段區(qū)域以外該變量不可見(或無法訪問)。詞法作用域里,取變量的值時(shí),會(huì)檢查函數(shù)定義時(shí)的文本環(huán)境,捕捉函數(shù)定義時(shí)對該變量的綁定。大多數(shù)現(xiàn)在程序設(shè)計(jì)語言都是采用靜態(tài)作用域規(guī)則,如 C/C++ 、 C# 、 Python 、 Java 、 JavaScript …… 相反,采用動(dòng)態(tài)作用域的變量叫做動(dòng)態(tài)變量。只要程序正在執(zhí)行定義了動(dòng)態(tài)變量的代碼段,那么在這段時(shí)間內(nèi),該變量一直存在;代碼段執(zhí)行結(jié)束,該變量便消失。這意味著如果有個(gè)函數(shù) f,里面調(diào)用了函數(shù) g,那么在執(zhí)行 g 的時(shí)候,f 里的所有局部變量都會(huì)被 g 訪問到。而在靜態(tài)作用域的情況下,g 不能訪問 f 的變量。動(dòng)態(tài)作用域里,取變量的值時(shí),會(huì)由內(nèi)向外逐層檢查函數(shù)的調(diào)用鏈,并打印第一次遇到的那個(gè)綁定的值。顯然,最外層的綁定即是全局狀態(tài)下的那個(gè)值。采用動(dòng)態(tài)作用域的語言有 Pascal 、 Emacs Lisp 、 Common Lisp (兼有靜態(tài)作用域)、 Perl (兼有靜態(tài)作用域)。C/C++ 是靜態(tài)作用域語言,但在宏中用到的名字,也是動(dòng)態(tài)作用域。

實(shí)踐

思考這么一段代碼:

function fun1() {
  var a = 2
  console.log(a)
}

function fun2() {
  var a = 3
  console.log(a)
  fun1()
}
 fun2()

答案會(huì)是多少呢?


2

當(dāng)然這個(gè)很好理解,js 是函數(shù)作用域,fun1 內(nèi)有 a,當(dāng)然會(huì)打印 fun1 內(nèi)的 a 的值,并沒有特殊之處,可是這個(gè)代碼呢:

var a = 2
function fun1() {
  console.log(a)
}

function fun2() {
  var a = 3
  console.log(a)
  fun1()
}
 fun2()

答案和之前依舊一樣,是不是這樣就有點(diǎn)反直覺了? fun1 內(nèi)沒有 a 的情況下不是應(yīng)該讀取 fan2 的 a 嗎?為什么會(huì)讀取 全局作用域的 a 呢?說好的作用域是一層一層向上的呢?

當(dāng)然,作用域確實(shí)是向上查找,可是 js 是靜態(tài)作用域(詞法作用域),并不是動(dòng)態(tài)作用域,所以他不會(huì)看函數(shù)的調(diào)用位置,而是定義位置,并且沿著定義位置向上查找。詞法作用域和動(dòng)態(tài)作用域的區(qū)別如下:

  • 詞法作用域是在 代碼解析(定義) 的時(shí)候確定的,關(guān)注的是函數(shù)在 何處定義 ,并從定義處向上查找作用域。
  • 動(dòng)態(tài)作用域是在 代碼運(yùn)行 的時(shí)候確定的,關(guān)注的是代碼在 何處調(diào)用 ,并從調(diào)用棧向上查找作用域。

所以現(xiàn)在很好理解,為什么 fun1 內(nèi)沒有 a 他會(huì)先去讀取全局的 a,而不是 fun2 的 a 了吧?不信可以看這個(gè)代碼:

function fun1() {
  console.log(a) // a is not defined
}

function fun2() {
  var a = 3
  console.log(a)

  fun1()
}
fun2()

當(dāng)然,js 有個(gè)特殊之處,就是 this,思考這段代碼:

this.a =  2

function fun1() {
  console.log(this.a) // 1
}

function fun2() {
  this.a = 1
  console.log(this.a) // 1

  fun1()
}
fun2()

是不是疑惑了,說好的從定義的地方向上查找呢,為什么會(huì)打印出執(zhí)行的作用域的值?

這里可以先說答案:因?yàn)?nbsp;this

this.a =  2
// this 指向 window

function fun1() {
  // 這里 this 還是指向 window
  console.log(this) // window
  console.log(this.a) // 1
}

function fun2() {
  // this 依舊指向 window,不信可以打印看看那
  console.log(this.a) // 2

  // 這里修改了外邊的 this.a
  this.a = 1
  // 打印修改后的值
  console.log(this.a) // 1

  fun1()
}
fun2()

所以明白了吧? 作用域依舊是在定義的地方向上查找,只不過是兩個(gè)函數(shù)都指向了同一個(gè) this 而已。

這里插一嘴,雖然我認(rèn)為 js 的 this 是一個(gè)設(shè)計(jì)的非常糟糕的東西(他完全不符合正常人的思維邏輯),我也非常非常久都不再使用 this,但是我認(rèn)為這個(gè)東西還是必須得理解的,不然早晚會(huì)搞出大麻煩,你可以不用,但是你必須要懂。

Ok, 接著上面所說,為什么兩個(gè)函數(shù)指向了同一個(gè) this(window)?這里就要深入的了解一下 this 的指向問題:this 究竟指向哪里,是都指向 window 么?顯然不是,看一下代碼:

this.n = 1

function fun2() {
  console.log(this.n) // 2
}
var a = {
  n: 2,
  fun1() {
    console.log(this) // {n: 2, fun1: function}
    console.log(this.n) // 2
    a.fun2()
  },
  fun2
}

a.fun1()

這里的 fun1 的 this 明顯指向了 a 本身,并不是 this,同樣 fun2 雖然定義在外部,但是也依然指向了 a ,是不是和之前想的不太一樣?fun2 定義在外邊,那么他的 this 應(yīng)該是 window 才對,打印的應(yīng)該是 1 才對啊,可能這個(gè)時(shí)候你就在想了,是不是 this 就是動(dòng)態(tài)作用域呢?并不! This 依舊是靜態(tài)作用域,參考這個(gè)代碼:

this.n = 1

function fun2() {
  console.log(this.n) // 1
}
var a = {
  n: 2,
  fun1() {
    fun2()
  },
  fun2
}

a.fun1()

發(fā)現(xiàn)區(qū)別了嗎?this 依舊是指向 window,這就說明 this 只是在定義的時(shí)候強(qiáng)行綁定了執(zhí)行他的環(huán)境,所以我們通過 a.fun2 調(diào)用,this 就指向 a,通過直接調(diào)用 fun2(實(shí)際等于 window.fun2),指向的則是 window。

當(dāng)然也有例外,比如箭頭函數(shù):

this.n = 1

const fun2 = () =>  {
  console.log(this.n)
}
var a = {
  n: 2,
  fun1() {
    // console.log(this)  // {n: 2, fun1: function}
    // console.log(this.n) // 2
    a.fun2()
    // fun2()
  },
  fun2
}

a.fun1()

箭頭函數(shù)中,不管你是 a.fun2 還是直接 fun2,指向的都是window,因?yàn)榧^函數(shù)的 this 固定指向他的父作用域,而根據(jù)靜態(tài)作用域的原則,他父作用域是定義時(shí)的作用域,也就是 window,所以不管怎么調(diào)用,他都是 window。通過以下這個(gè)例子更能看出來這一點(diǎn),箭頭函數(shù)的 this 固定指向他定義的作用域:

var n = 1
var a = () => {
    console.log(this.n)
}

var b={
    n: 2,
    fun2: {
        n: 3,
        fun1:a,
        fun() {
            a() // 1
            console.log(this) // {n: 3,     fun1:function, fun: function}
            console.log(this.n) // 3
            this.fun1() // 1

        }
    }
}
b.fun2.fun()

通過這個(gè)你就能發(fā)現(xiàn),箭頭函數(shù)的 this 并不指向調(diào)用他的對象,也不是指向調(diào)用他的對象的父作用域,而是指向他定義的位置的父作用域,不管你在哪里調(diào)用,都是同一個(gè)指向。

總結(jié)

總結(jié)一下,對于this,你只需要記住這幾點(diǎn):

  • 正常情況下 this 指向調(diào)用他的上下文
  • 箭頭函數(shù)的 this 指向他的父作用域的 this(靜態(tài)作用域、靜態(tài)作用域、靜態(tài)作用域)
  • new 會(huì)創(chuàng)建一個(gè)新的對象,this 指向這個(gè)對象,詳情可以自行了解 new
  • call、bind、apply 會(huì)改變 this 的指向,詳情自行了解
a.xx()
xx 內(nèi)的 this 就是 a
a.b.xx()
xx 內(nèi)的 this 就是 b

.xxx,. 之前的上下文就是他的 this。 而在非嚴(yán)格模式的全局環(huán)境中(嚴(yán)格模式會(huì)報(bào)錯(cuò)),實(shí)際我們定義的變量都是掛載在 window 下,所以 this 指向的是 window。

到此這篇關(guān)于js詞法作用域與this的文章就介紹到這了,更多相關(guān)js詞法作用域與this內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • js學(xué)習(xí)總結(jié)_基于數(shù)據(jù)類型檢測的四種方式(必看)

    js學(xué)習(xí)總結(jié)_基于數(shù)據(jù)類型檢測的四種方式(必看)

    下面小編就為大家?guī)硪黄猨s學(xué)習(xí)總結(jié)_基于數(shù)據(jù)類型檢測的四種方式(必看)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-07-07
  • js中使用DOM復(fù)制(克?。┲付ü?jié)點(diǎn)名數(shù)據(jù)到新的XML文件中的代碼

    js中使用DOM復(fù)制(克?。┲付ü?jié)點(diǎn)名數(shù)據(jù)到新的XML文件中的代碼

    使用DOM復(fù)制(克隆)指定節(jié)點(diǎn)名數(shù)據(jù)到新的XML文件中 ,用到三個(gè)類的相關(guān)知識(shí)點(diǎn) : DOMDocument - DOMNodeList - DOMNode
    2011-07-07
  • 詳解Nuxt.js 實(shí)戰(zhàn)集錦

    詳解Nuxt.js 實(shí)戰(zhàn)集錦

    這篇文章主要介紹了Nuxt.js 實(shí)戰(zhàn)集錦,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • JS/HTML5游戲常用算法之碰撞檢測 像素檢測算法實(shí)例詳解

    JS/HTML5游戲常用算法之碰撞檢測 像素檢測算法實(shí)例詳解

    這篇文章主要介紹了JS/HTML5游戲常用算法之碰撞檢測 像素檢測算法,結(jié)合實(shí)例形式詳細(xì)分析了javascript像素檢測碰撞算法的原理、實(shí)現(xiàn)步驟及相關(guān)操作技巧,需要的朋友可以參考下
    2018-12-12
  • electron的webview和內(nèi)嵌網(wǎng)頁通信的方法

    electron的webview和內(nèi)嵌網(wǎng)頁通信的方法

    在 Electron 的世界里,webview 標(biāo)簽相當(dāng)于一個(gè)小盒子,里面可以裝一個(gè)完整的網(wǎng)頁,就像一個(gè)迷你瀏覽器,這篇文章主要介紹了electron的webview和內(nèi)嵌網(wǎng)頁如何通信,需要的朋友可以參考下
    2024-04-04
  • webpack@v4升級踩坑(小結(jié))

    webpack@v4升級踩坑(小結(jié))

    這篇文章主要介紹了webpack@v4升級踩坑(小結(jié)),之前就嘗試了升級,由于部分插件的原因,未能成功,今天就來試一下在我的項(xiàng)目中升級會(huì)遇到哪些坑。感興趣的小伙伴們可以參考一下
    2018-10-10
  • window.returnValue使用方法示例介紹

    window.returnValue使用方法示例介紹

    returnValue是javascript中html的window對象的屬性,目的是返回窗口值,下面有個(gè)示例,大家可以感受下
    2014-07-07
  • js Calender控件使用詳解

    js Calender控件使用詳解

    這篇文章主要介紹了js Calender控件使用詳解,需要的朋友可以參考下
    2015-01-01
  • ES6模塊化的import和export用法方法總結(jié)

    ES6模塊化的import和export用法方法總結(jié)

    這篇文章主要介紹了ES6模塊化的import和export用法方法總結(jié),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-08-08
  • javascript中this關(guān)鍵字詳解

    javascript中this關(guān)鍵字詳解

    本文介紹了javascript中this關(guān)鍵字,并將有關(guān)this的關(guān)鍵字知識(shí)列成一個(gè)list,會(huì)有助于我們理清思路,是一個(gè)很好的學(xué)習(xí)方法。強(qiáng)烈推薦。
    2016-12-12

最新評論

保德县| 德江县| 平远县| 清苑县| 安宁市| 中宁县| 滦南县| 平顺县| 德清县| 新泰市| 郧西县| 龙游县| 高密市| 乳山市| 锡林郭勒盟| 通城县| 金坛市| 霍州市| 香格里拉县| 文山县| 城固县| 金乡县| 顺义区| 秭归县| 永清县| 邵阳市| 双城市| 白玉县| 河曲县| 黄大仙区| 平山县| 遂溪县| 深泽县| 浦北县| 灵寿县| 醴陵市| 卢湾区| 同仁县| 邯郸市| 扶绥县| 岗巴县|