new/類/null/+/PrimitiveValue/valueOf/toString/環境/HTML 指令碼元素屬性

被咯苏州發表於2024-06-07

new

function myObjCreate(proto){
function F(){}
F.prototype = proto
return new F();
}
function myNew(F,...args){
let obj = myObjCreate(F.prototype)
let res = F.call(obj,...args);
return typeof res === 'object' && res !== null ? res : obj;
}
如果建構函式返回的是基本型別(如字串、數字、布林值、null、undefined),這些返回值會被忽略,new運算子會返回新建立的物件。

類只能用new運算來建立,而不能使用“()”來做函式呼叫
new AClass() // ok
AClass() // TypeError: Class constructor AClass cannot be invoked without 'new'

obj.foo() // ok
new obj.foo() // TypeError: obj.foo is not a constructor

類:只可以做new運算;
方法:只可以做呼叫“( )”運算;
一般函式:(除部分函式有特殊限制外,)同時可以做new和呼叫運算。
區分 3 者
類:定義類的方法是使用class關鍵字。
方法:附加在物件上的函式,通常定義在物件字面量或者類內部
一般函式:一般函式是普通的函式宣告或函式表示式
function myExtends(Child, Parent) {
// 建立一個新的物件,該物件的原型指向 Parent.prototype
Child.prototype = Object.create(Parent.prototype);
// 修復 Child.prototype.constructor 指向 Child 自身
Child.prototype.constructor = Child;
// 允許 Child 訪問 Parent
Child.proto = Parent;
}

在類宣告中,如果是類靜態宣告,也就是使用static宣告的方法,那麼主物件就是這個類,例如AClass。
就是一般宣告,那麼該方法的主物件就是該類所使用的原型,也就是AClass.prototype。
第三種情況,如果是物件宣告,那麼方法的主物件就是物件本身。

類宣告中 extends 是 null,那麼構造方法中沒有 this 也不能呼叫 super()。
class MyClass extends null {
}
new 後報錯 Uncaught TypeError: Super constructor null of MyClass is not a constructor
class MyClass extends null {
constructor() {
}
}
new 後報錯 Uncaught ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor

物件和陣列的區別

物件和陣列都是用來儲存資料的兩種結構。陣列是一種特殊的物件,它用數字作為標籤(索引)來儲存資料,比如a[0]表示陣列a中的第一個元素。而物件用名字作為標籤來儲存資料,比如obj.name表示物件obj中的一個叫name的屬性。

JavaScript中的資料結構主要有兩種:
索引陣列(用數字索引的陣列)
關聯陣列(用名字作為標籤的物件)

null

null是一個物件型別
原子物件:原子物件是最基本的物件,它的原型是null。一個原子物件沒有任何屬性,也沒有原型。
class MyClass extends null {}
let instance = new MyClass(); console.log(Object.getPrototypeOf(MyClass.prototype)); // 輸出 null console.log(instance); // 輸出 {}

+

[] + {} // 空陣列[]被轉換成空字串'',空物件{}被轉換成字串'[object Object]',然後這兩個字串連線起來。
'[object Object]'
{} + [] // {}被視為一個空的程式碼塊,所以沒有任何作用,而空陣列[]被轉換成數字0。
0
{} + {} // 第一個 {} 被視為程式碼塊,後面的 +{} 嘗試將 {} 轉換為數值,結果是 NaN,這裡的+號作為一元運算子
NaN
[] + [] // 兩個空陣列都被轉換成空字串,連線起來仍然是空字串。
''
上面執行反應了+符號在字串拼接,數字計算,一元運算子
上面有兩個案例是因為 js 的【自動分號插入(ASI)】機制,可以看成下面的結果
{}; +[]

PrimitiveValue

五種PrimitiveValue內部槽:number,string,boolean,symbol,bigint。
上面這 5 種在經過ToPrimitive(hint) 轉換時直接呼叫x.valueOf()
返回原始值。
在預設情況下,JavaScript更傾向於把物件轉換為數字型別。因為hint 預設是 number

valueOf/toString

如果使用者程式碼試圖得到“number”型別,但x.valueOf()返回的是一個物件,那麼就還會呼叫x.toString(),並最終得到一個字串。
let x = {
valueOf() {
return {}; // 返回一個物件
},
toString() {
return "Hello";
}
};
// 嘗試將 x 轉換為數字
console.log(x + 5); // 輸出 "Hello5"

環境:

全域性環境(Global Environment):宣告環境+物件環境
宣告環境:函式環境(Function Environment)/模組環境(Module Environment)/Eval環境(Eval Environment)
宣告環境(Declarative Environment):抽象的概念,用於儲存透過 var、let、const 宣告的變數和函式宣告。
物件環境(Object Environment):全域性物件(如瀏覽器中的 window 物件或 Node.js 中的 global 物件),其中包含全域性變數和函式作為其屬性。

變數環境(Variable Environment):主要用於記錄透過 var 宣告的變數和函式宣告。
詞法環境(Lexical Environment):主要用於記錄透過 let、const 和函式宣告的變數。

HTML 指令碼元素屬性:async 與 defer 與 type=’module’

https://cdn-images-1.medium.com/v2/resize:fit:1117/1*nmzAKz_RSbZ-E-m5B6pPaA.png

相關文章