1. JavaScript有哪些數據類型,它們的區別?
JavaScript共有八種數據類型,分別是Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt。
其中Symbol 和BigInt 是ES6 中新增的數據類型:
Symbol 代表創建後獨一無二且不可變的數據類型,它主要是為了解決可能出現的全局變量衝突的問題。
BigInt 是一種數字類型的數據,它可以表示任意精度格式的整數,使用BigInt 可以安全地存儲和操作大整數,即使這個數已經超出了Number 能夠表示的安全整數範圍。
2. null和undefined區別
首先Undefined 和Null 都是基本數據類型,這兩個基本數據類型分別都只有一個值,就是undefined 和null。
undefined 代表的含義是未定義,null 代表的含義是空對象。一般變量聲明了但還沒有定義的時候會返回undefined,null主要用於賦值給一些可能會返回對象的變量,作為初始化。
undefined 在JavaScript 中不是一個保留字,這意味著可以使用undefined來作為一個變量名,但是這樣的做法是非常危險的,它會影響對undefined 值的判斷。我們可以通過一些方法獲得安全的undefined 值,比如說void 0。
當對這兩種類型使用typeof 進行判斷時,Null 類型化會返回"oobject",這是一個歷史遺留的問題。當使用雙等號對兩種類型的值進行比較時會返回true,使用三個等號時會返回false。
3. typeof NaN 的結果是什麼?
NaN 指“不是一個數字"(not a number),NaN 是一個“警戒值"(sentinel value,有特殊用途的常規值),用於指出數字類型中的錯誤情況,即“執行數學運算沒有成功,這是失敗後返回的結果"。
NaN 是一個特殊值,它和自身不相等,是唯一一個非自反(自反,reflexive,即x === x 不成立)的值。而NaN !== NaN 為true。
4. 資料型別轉換
在JavaScript中型別轉換有三種情況:
轉換為數字(呼叫Number(),parseInt(),parseFloat()方法)
轉換為字串(呼叫.toString()或String()方法)
轉換為布林值(呼叫Boolean()方法)
null、undefined沒有.toString方法
轉換為數字
Number():可以把任意值轉換成數字,如果要轉換的字串中有不是數字的值,則會返回NaN
5. js中&&是什麼運算符?
當&&連接語句時,兩邊的語句會轉化為布爾類型(Boolean),然後再進行運算,具體的運算規則如下:
1、兩邊條件都為true時,結果才為true;
2、如果有一個為false,結果就為false;
3、當第一個條件為false時,就不再判斷後面的條件
注意:當數值參與邏輯與運算時,結果為true,那麼會返回的會是第二個為真的值;如果結果為false,返回的會是第一個為假的值。
&&運算符的三個層次理解
第一層理解:當操作數都是布爾值時,&&運算符對兩個值執行布爾與(and)操作,只有第一個操作數和第二個操作數都是true,
它才返回true。
6.DOM元素,到底是什麼?
文件物件模型(Document Object Model, DOM)是 HTML、XML 和 SVG 文件的程式介面。它提供了一個文件(樹)的結構化表示法
並定義讓程式可以存取並改變文件架構、風格和內容的方法。DOM 提供了文件以擁有屬性與函式的節點與物件組成的結構化表示。
節點也可以附加事件處理程序,一旦觸發事件就會執行處理程序。 本質上,它將網頁與腳本或程式語言連結在一起。
7.JavaScript事件傳播
事件傳播是一種機制,它定義事件如何通過 DOM 樹傳播或傳播到達目標,以及之後發生的事情。
讓我們在一個例子的幫助下理解這一點,假設你已經在一個巢狀在一個段落(即<p>元素)中的超連結(即 <a> 元素)上
分配了一個 click 事件處理程式。現在,如果單擊該連結,將執行處理程式。
但是,如果將 click 事件處理程式分配給包含該連結的段落,而不是連結,那麼即使在這種情況下,單擊該連結仍將觸發處理程式。
這是因為事件不僅影響生成事件的目標元素 - 它們在 DOM 樹中上下移動以到達目標。這稱為事件傳播。
捕獲階段
在捕獲階段,事件從 Window 向下傳播通過 DOM 樹到目標節點。例如,如果使用者單擊超連結,則該單擊事件將通過元素 <html> ,<body> 元素和包含該連結的<p>元素。
此外,如果目標元素的任何祖先(即父,祖父等)和目標本身具有針對該型別事件的特別註冊的捕獲事件監聽器,則在該階段期間執行這些監聽器。
冒泡階段
在冒泡階段,恰好相反。在這個階段,事件傳播或冒泡 DOM 樹,從目標元素到視窗,逐個訪問目標元素的所有祖先。例如,如果使用者單擊超連結,則該單擊事件將通過 <p> 包含連結, <body> 元素, <html> 元素和 document 節點的元素。
此外,如果目標元素的任何祖先和目標本身具有為該型別的事件分配的事件處理程式,則在此階段執行這些處理程式。在現代瀏覽器中,預設情況下,所有事件處理程式都在冒泡階段進行註冊。
7.preventDefault及stopPropagation函式區別
preventDefault(): 預防作用的元素預設事件發生,如果只是要預防 <a href="#"> 回到頁首,加上這個。
stopPropagation(): 停止作用的元素冒泡,其父元素的事件會停止發生,如果作用元素的父元素也有綁定一些行為,不想要他們在這時候產生行為時,就加上這個。
最後說一下return false; 這是jQuery中提供
它幫我們同時做了:
- event.preventDefault();
- event.stopPropagation();
8.什麼是event.target?
指向最初觸發事件的DOM物件。與 event.currentTarget 屬性不同的是,event.currentTarget屬性總會指向目前於冒泡或捕捉階段
正在處理該事件之事件處理器所註冊的DOM物件,而event.target屬性則是永遠指向觸發事件的DOM物件。
9.Scope作用域?
作用域就是一個獨立的區域,包裹著變量,避免變量暴露。也就是說作用域最大的用處就是隔離變量,不同作用域下同名變量不會有衝突。
在 ES6 以前,唯一產生作用域的方法就是宣告 function,每一個 function 都有自己的作用域,在作用域外就存取不到這個 function 內部所定義的變數。
因此 JavaScript 的作用域其實可分為三個層級:
Global Level Scope:全域作用域
Function Level Scope:函式作用域
Block Level Scope(ES6):區塊作用域
也就是說,變數作用域的範圍,其實就取決於這個變數的宣告方式,以及在哪進行宣告。
E6 以後的作用域:Block Scope
接著再回到 ES6,新增了區塊作用域(block scope)的概念,也就是以 let 和 const 來宣告變數。
在第三週的 ES6 部份我們也曾提到,以 let、const 或 var 方式來宣告變數,最大的差別在於變數的作用域範圍不同:
var:作用於整個函數範圍中(function scope)
let 與 const:均為區塊作用域(block scope),如此可避免污染到大括號 {...} 外的變數
而 let 和 const 最大的區別,在於該變數是否能被重新賦值:
const(constant):常數宣告後就不能再重新賦值,並且在宣告時就必須賦值
let:可重新賦值,也可先進行宣告但不賦值
10.Closure 閉包
閉包(Closure)是擁有閒置變數(Free variable)的運算式。閒置變數真正扮演的角色依當時語彙環境(Lexical environment)而定。
支援閉包的程式語言通常具有一級函式(First-class function)。建立函式不等於建立閉包。如果函式的閒置變數與當時語彙環境綁定,該函式才稱為閉包。
那麼何為閒置變數?閒置變數是指對於函式而言,既非區域變數也非參數的變數,像區域變數或參數,其作用範圍基本上在被定義的函式範 圍中。它是被綁定變數(Bound variable)。
11.JavaScript Prototype (原型) 是什麼?
所有JavaScript中的函式都有一個內建的prototype屬性,指向一個特殊的prototype物件
prototype物件中也有一個contructor屬性,指向原來的函式,互相指來指去會讓你覺得有點怪異,但設計就是如此。
再來是__proto__這個內部屬性,它是一個存取器(accessor)屬性,意思是用getter和setter函式合成出來的屬性,我們可以用它來更加深入理解整個原型的樣貌。
__proto__是每一個JavaScript中物件都有的內部屬性,代表該物件繼承而來的源頭,也就是指向該物件的原型(prototype),它會用來連接出原型鏈,或可以理解為原型的繼承結構。
12.什麼是IIFE,它的用途是什麼?
不需要呼叫此函式,也能執行 (立刻執行)
IIFE 最主要目的是避免污染到全域執行環境並照成污染與衝突
限制作用域的用途,「立即函式」無法在外層呼叫
變數的作用域只在函式內,在外層無法取得變數
「立即函式」本身是表達式,所以也能回傳一個值
因此,透過IIFEs,我們可以發現,在IIFEs中所建立的變數,都不會影響到Global Execution Context所建立的變數,也就是說,透過IIFEs,它避免了我們的變數間可能會互相干擾覆蓋的情況。
13.`Generator`函數是什麼,有什麼作用?
宣告一個 Generator 的關鍵字是 function*,function 關鍵字後面接著一個星號 *
Generator 函數裡面使用 yield 關鍵字,來定義和暫停不同的內部執行狀態
var g = gen(); 執行 Generator 函數會返回一個 Generator Object,其本質上是一個 Iterator。
一個 Generator 的運作有點像是一個狀態機 (state machine),會一直改變內部的不同狀態:起始狀態 -> 繼續 -> 暫停 (狀態 1) -> 繼續 -> 暫停 (狀態 2) -> 繼續 -> .... -> 結束 (狀態 N)
一個 Generator Object 的起始狀態會先暫停什麼都不做,而每次執行 next() 方法,就會繼續執行函數,直到遇到下一個 yield 關鍵字,又會暫停函數的執行,而每一次暫停時會 yield (產出) 一個當前狀態值。
展開運算子( Spread Operator )
//===========過去寫法===========
let groupA = ['爸爸', '媽媽'];
let groupB = ['老大','老二','老么'];
const groupAll = groupA.concat(groupB);
console.log(groupAll);
// ["爸爸", "媽媽", "老大", "老二", "老么"];
//===========新的寫法===========
let groupA = ['爸爸', '媽媽'];
let groupB = ['老大','老二','老么'];
const groupAll = [...groupA, ...groupB]; //拆解完後,再用陣列[]包起來,產生新的陣列
console.log(groupAll);
// ["爸爸", "媽媽", "老大", "老二", "老么"];
沒有留言:
張貼留言