深入聊聊JavaScript

2022-06-16 14:02:32
本篇文章給大家帶來了關於的相關知識,其中主要包括了為什麼需要JavaScript引擎、瀏覽器核心與js引擎的關係、環境變數與記錄等等內容,下面一起來看一下,希望對大家有幫助。

【相關推薦:、】

TypeScript 會取代JavaScript嗎?

  1. TypeScript只是帶來了型別的思維
    因為JavaScript本身長期沒有變數、函數引數等型別進行限制
    這可能給我們專案帶來某種安全的隱患
  2. 在之後的JavaScript社群中出現了一系列的型別約束方案
    2014年,Facebook推出來flow來對JavaScript進行型別檢查

3.Type源於JavaScript,歸於JavaScript

為什麼需要JavaScript引擎

高階程式語言都需要轉換成最終的機器指令來執行
事實上我們編寫的JavaScript無論交給瀏覽器或者Node執行,最後都是需要被CPU執行的
所以我們需要JavaScript引擎幫助我們將JavaScript程式碼翻譯成CPU指令來執行

瀏覽器核心和JS引擎的關係

這裡我們以WebKit為列,WebKit事實上由兩部分組成:
WebCore:負責HTML解析、佈局、渲染等等相關的工作
JavaScriptCore:解析、執行JavaScript程式碼

變數環境 與 記錄

VO(Variable Object)變數物件 在最新的ECMA標準中,VO已經有另外一個稱呼了變數環境 VE

GO(Clobal Object)全域性物件,全域性執行上下文

AO(Activation Objece)包括了函數執行上下文

記憶體管理 和 閉包

  1. 認識記憶體管理

在這裡插入圖片描述

JS的記憶體管理

JavaScript會在定義變數時為我們分配記憶體
JS對於基本資料型別記憶體的分配會在執行時,直接在棧空間進行分配;
JS對於複雜資料型別記憶體的分配會在堆記憶體中開闢一塊空間,並將這塊空間的指標返回值變數參照

JS的垃圾回收

因為記憶體的大小是有限的,所以當記憶體不再需要的時候,我們需要對其進行釋放,以便騰出更多的記憶體空間

垃圾回收的英文是 Garbage Collection 簡稱GC
對於那先不再使用的物件,我們都稱之為是垃圾,它需要被回收,以釋放更多的記憶體空間
而我們的語言執行環境,比如java的執行環境JVM,JavaScript的執行環境js引擎都會記憶體垃圾回收器
垃圾回收器我們也簡稱GC,所以哎很多地方你看到 GC其實指的是垃圾回收器

深入閉包

在電腦科學中對閉包的定義(維基百科):
閉包(英語:Closure),又稱詞法閉包(Lexical Closure) 或函數閉包(function closures);
是在支援頭等函數的程式語言中,實現詞法系結的一種技術;
閉包在實現上是一個結構體,它儲存了一個函數和一個關聯的環境(相當於一個符號查詢表);
閉包跟函數最大的區別在於,當捕捉閉包的時候,它的自由變數會在捕捉時被確定,這樣即使脫離了捕捉時的上下文,它也能照常執行

閉包的概念出現於60年代,最早實現閉包的程式時Scheme,那麼我們就可以理解為什麼JavaScript中有閉包;
因為JavaScript中有大量的設計是來源於Scheme的;
在這裡插入圖片描述

我們再來看一下MDN對JavaScript閉包的解釋:
一個函數和對其周圍狀態(lexical environment,詞法環境) 的參照捆綁在一起(或者說函數被參照包圍),這樣的組合就是閉包
也就是說,閉包讓你可以在一個內層函數中存取到其外層函數的作用域;
在JavaScript中,每當建立一個函數,閉包就會在函數建立的同時被建立出來;

function foo() {
    var name = 'why'
    var age = 18
    function bar() {
        console.log('bar ',name)
    }
    return bar}var fun = foo()fun()

總結:
一個普通的函數function,如果它可以存取外層作用於的自由變數,那麼這個函數就是一個閉包;
從廣義的角度來說:JavaScript中的函數都是閉包;
從狹義的角度來說:JavaScript中一個函數,如果存取了外層作用於的變數,那麼它是一個閉包;

this指向

在全域性作用域下:
瀏覽器:window
node環境:{}

箭頭函數 arrow function

箭頭函數是ES6 之後增加的一種編寫函數的方法,並且它比函數表示式更加簡潔;
箭頭函數不會繫結this、arguments屬性;
箭頭函數不能作為建構函式來使用(不能和new一起來使用,會丟擲錯誤)

認識arguments

arguments是一個對應於 傳遞給函數的引數的類(偽)陣列(array-like) 物件

理解JvaScript純函數

函數語言程式設計中有一個非常重要的概念叫做純函數,JavaScript符合函數語言程式設計的規範,所以也有純函數的概念;

純函數的維基百科定義:
在程式設計中,若一個函數符合以下條件,那麼這個函數輩稱為純函數
此函數在相同的輸入值時,需要產生相同的輸出
函數的輸出和輸入值以外的其他隱藏資訊或狀態無關,也和由I/O裝置產生的外部輸出無關
改函數不能有語意上可觀察的函數副作用,諸如 「觸發事件」,使輸出裝置輸出,或更改輸出值以外物件的內容等
總結:
確定的輸入,一定產生確定的輸出;
函數在執行過程中,不能產生副作用;

副作用:

JavaScript 柯里化

柯里化也是屬於函數語言程式設計裡面一個非常重要的概念
維基百科解釋:
在電腦科學中,柯里化(Currying) ,又譯為卡瑞化 或加里化
是八接收多個引數的函數,變成接收一個單一引數(最初函數的第一個引數)的函數,並且返回接受餘下的引數,而且返回結果的新函數
柯里化聲稱:如果你固定某些引數,你將得到接受餘下引數的一個函數

總結:
只傳遞給函數一部分引數來呼叫它,讓它返回一個函數區處理剩餘的引數;
這個過程就稱為柯里化

為什麼需要柯里化:
在函數語言程式設計中,我們其實往往希望一個函數處理的問題儘可能的單一,而不是將一大堆的處理過程交給一個函數來處理

function foo(x,y,c) {
    return x + y + c
}
console.log(foo(10,20,30))

//柯里化
function sum(x) {
    return function(y) {
        return function(z) {
            return x + y + z
        }
    }
}
var a = sum(10)(20)(30)
console.log(a )

//簡化柯里化
var sum2 = x => y => z => {
    return x + y + z
}
console.log(sum2(10)(20)(30 ))

組合函數

組合函數(Compose) 函數是在JavaScript開發中一種對函數的使用技巧、模式:
比如我們現在需要對某個資料進行函數的呼叫,執行兩個函數fn1 和 fn2,這兩個函數是依次執行的
那麼如果我們每次都需要進行兩個函數的呼叫,操作上就會顯示的重複
那麼是否可以將這兩個函陣列合起來,自動依次呼叫呢?
這個過程就是對函數的組合,我們稱之為組合函數(Compose Function)

其他內容

with語句

with 語句
+作用: 可以形成自己的作用域
不建議使用with語句 ,因為它可能是混淆錯誤和相容性問題的根源

var obj2 = {name:'Tom',age:18,message:'obj2'}

// var message = "hello world"

function foo() {
function bar () {
     with(obj2) {
          console.log(message)
     }
}
bar()
}
foo()
eval函數

eval是一個特殊的函數,它可以將傳入的字串當作JavaScript 程式碼來執行

   var strFn = 'var message = "Hello world"; console.log(message);';
   eval(strFn)

不建議在開發中使用eval:
eval程式碼的可讀性非常的差(程式碼的可讀性是高品質程式碼的重要原則);
eval是一個字串,那麼有可能在執行的過程中輩可以篡改,那麼可能會造成被攻擊的風險;
eval的執行必須經過JS直譯器,不能不被JS引擎優化;

嚴格模式 strict Mode

 嚴格模式是一種具有限制性的JavaScript模式,從而使程式碼隱式的脫離了"懶散(sloppy) 模式"
 支援嚴格模式的瀏覽器在監測到程式碼中有嚴格模式時,會以更加嚴格的方式對程式碼進行監測和執行

 嚴格模式通過丟擲錯誤來消除一些原有的靜默(silent)錯誤
 嚴格模式讓Js引擎週期執行程式碼時可以進行更多的優化(不需要對一些特殊的語法進行處理)
"use strict"; // 開啟嚴格模式var message = "hello world"console.log(message)

嚴格模式限制
這裡我們來說幾個嚴格模式下的嚴格語法限制:
JavaScript被設計為新手開發者更容易上手,所以有時候本來錯誤語法,被認為也是可以正常被解析的
但是在嚴格模式下,這種失誤會被當成錯誤,以便可以快速的發現和修正

  1. 無法意外的建立全域性變數
// 1. 意外建立全域性變數
    message = "Hello world"
    console.log(message)

    function foo() {
        age = 20
    }
    foo()
    console.log(age)
  1. 嚴格模式會時引起靜默失敗(silently fail ,注:不報錯也沒有任何效果)的賦值操作丟擲異常
//預設靜態錯誤
true.name ='xiaoluo';
NaN = 123
  1. 嚴格模式下試圖刪除不可刪除的屬性
  2. 嚴格模式不允許函數引數有相同的名稱
// 不允許函數引數有相同的名稱function foo(x,y,x) {
    console.log(x,y,x)}foo(10,20,30)
  1. 不允許0 的八進位制語法
var num = 0o123 // 八進位制
var num2 = 0x123 // 十六進位制
console.log(num,num2)
  1. 在嚴格模式下, 不允許使用with
var obj2 = {name:'Tom',age:18,message:'obj2'}

with(obj2) {
      console.log(message)
     }
  1. 在嚴格模式下,eval 不再為上層參照變數
var strFn = 'var message = "Hello world"; console.log(message);';
eval(strFn)
console.log(message)
  1. 嚴格模式下,this繫結不會預設轉成物件
    嚴格模式下,自執行函數會指向undefined
function foo() {
    console.log(this) //undefined
}
foo()

【相關推薦:、】

以上就是深入聊聊JavaScript的詳細內容,更多請關注TW511.COM其它相關文章!