01、Object物件
Object 是 JavaScript 的一種 資料型別,它用於儲存各種鍵值集合和更復雜的實體,是一組資料和功能的集合。JS中幾乎所有物件都是繼承自Object,Array、RegExp、Math、Map、Set都是他的子型別。
- 標準物件結構:
{ key(字串/Symbol) : value(任意型別), ...}
- 建立方式:
new Ojbect()
、字面量{key:value,key2:value2}
、Object.create(obj)
。- 使用
new 構造器()
,實現可重用的物件建立,任何函式都可以用於構造器(箭頭函式除外),一般約定首字母大寫,沒有return
返回值。
- 使用
- 使用方式:
物件.屬性=value
,物件["屬性名"]=value
,屬性(Key)存在則賦值,不存在則建立並賦值。 - 刪除屬性:
delete obj.prop
- 檢測屬性:
"key" in obj
,返回bool
- 遍歷屬性:
for(let key in obj)
迴圈所有key。
屬性/方法 | 描述 |
---|---|
✅靜態屬性/方法 | |
Object.create(proto, propertiesObject) | 使用指定的原型物件和屬性建立一個新物件 |
Object.assign(target,...source) IE? | 合併多個source 物件到target 並返回,複製一級屬性的值,不能作為深複製 |
Object.defineProperty(obj,prop,descriptor) | 給物件新增屬性,透過descriptor配置屬性資訊。這是Vue2實現雙向繫結的關鍵(透過get、set攔截資料的變化) |
Object.entries(obj) IE? | 返回給定物件可列舉屬性的[key, value] 陣列(二維陣列) |
Object.keys(obj) | 返回給定物件可列舉屬性key 組成的陣列 |
Object.values(obj) IE? | 返回給定物件可列舉屬性值value 組成的陣列 |
Object.freeze(obj) | 凍結物件:其他程式碼不能刪除或更改任何屬性,相當於只讀 |
Object.getOwnPropertyDescriptor(o,p) | 返回物件指定自有屬性的描述符,IE?,描述符就是屬性的詳細描述資訊 |
Object.getOwnPropertyNames(obj) | 返回物件所有自有屬性名(包括不可列舉屬性,不包括 Symbol 名稱的屬性)組成的陣列 |
Object.getPrototypeOf(obj) | 返回指定物件的原型物件,同obj.__proto__ ,(prototype /ˈprəʊtətaɪp/ 原型) |
Object.is(v1,v2) | 判斷兩個值是否為同一個值,支援值型別、引用型別 |
Object.isSealed() | 判斷物件是否被密封,Object.seal(obj) 密封一個物件,只可讀、寫現有屬性值 |
✅建構函式 | |
Object() | 建構函式將給定的值包裝為一個新物件 |
✅例項屬性/方法(Object.prototype.) | |
constructor | 指向 Object 建構函式 |
proto | 指向例項化的原型物件,推薦Object.getPrototypeOf() |
hasOwnProperty(prop) | 判斷指定物件自身是否存在指定屬性 |
propertyIsEnumerable(prop) | 判斷屬性是否可列舉,列舉屬性可被for...in 迴圈迭代 |
isPrototypeOf(obj) | 判斷是否在另一個物件的原型鏈上 |
toString() | 返回字串,可以重寫。toLocaleString() 預設呼叫 toString() |
valueOf() | 返回物件的原始值,(new Object(3)).valueOf(); //3 |
const obj1={};
const obj2={
name:"zhagnsan",
"age":"3",
school:{ //屬性值也是物件
name:"龍騰幼兒園",
address:"那邊",
},
sayHello:function(name){ //屬性值是函式
console.log("hello "+name);
},
}
obj2.sayHello("sam");
obj2.birthday="2022-12-12";//賦值操作:屬性(Key)存在則賦值,不存在則建立+賦值
//可以用null為原型建立一個乾淨的物件,不會從從Object.prototype繼承任何屬性方法
const nobj = Object.create(null, { name: { value: "sam", enumerable: true } });
nobj.age = 20;
nobj.toString=Object.prototype.toString; //賦予toString()方法
Object.getOwnPropertyNames(["a","b"]) //[ "0", "1", "length" ]
Object.keys(["a","b"]) //[ "0", "1" ]
Object.getPrototypeOf([]); //Array []
const obj={name:"sam",sex:"male",say:function(){}};
obj.hasOwnProperty("name"); //true
obj.propertyIsEnumerable("name"); //true
obj.toString = function(){return JSON.stringify(this)};
1.1、物件屬性Descriptor
?透過 Object.getOwnPropertyDescriptor(obj,propertyName) 方法可以獲取一個屬性的完整自有屬性資訊,返回的是一個“屬性描述符”Descriptor物件。Descriptor主要結構如下,Object.create(proto, propertiesObject)的第二個引數也是用的這個結構來描述屬性。
let descriptor = {
enumerable: false, //是否支援列舉
configurable: false, //如果為 true,則此屬性可以被刪除
writable: false, //是否只讀,true=可讀可寫
value: "value", //屬性的值
get() { },
set() { },
}
let pobj = { //Object.create(proto, propertiesObject)的第二個引數
proName1: descriptor,
proName2: descriptor,
}
?透過 Object.defineProperty(obj, propertyName, descriptor) 方法可新增/設定一個屬性,屬性描述符descriptor
預設值都是false
。JS的一些內建屬性就是隻讀、不可刪除的,如Math.PI
。
function User(name, age) {
this.name = name;
this.age = age ? age : 18;
function sayHi() { console.log("Hi,I'm " + name) };
}
let u1 = new User("sam");
let pname = Object.getOwnPropertyDescriptor(u1, "name");
//設定name值不可更改
Object.defineProperty(u1, "name", { writable: true });
1.2、getter/setter屬性訪問器
物件中常用的屬性都屬於“資料屬性”,只存放資料沒有額外邏輯。而訪問器屬性(accessor property),表現形式和普通屬性一樣,本質上就是一個取值、設定值的函式,可自定義邏輯,如資料合法性驗證。
- set(value):設定資料的
setter
方法,引數為屬性值 - get():獲取資料的
getter
方法,無引數,返回屬性值。
» 透過字面量定義和使用:
let obj = {
age: 18,
set name(value) {
let vs = String(value);
if (!vs || vs.length < 4 || vs.length > 12) {
throw Error("值必須是4到12的有效字元");
}
this._name = value;
},
get name() {
this._name ??= "empty";
return this._name;
}
};
//使用
obj.name = 'sam'; //Uncaught Error: 值必須是4到12的有效字元
obj.name = 'sam2';
console.log(obj.name); //sam2
Object.getOwnPropertyDescriptor(obj, 'name'); //{enumerable: true, configurable: true, get: ƒ, set: ƒ}
» 透過 Object.defineProperty(obj, propertyName, descriptor) 給屬性新增訪問器:
function User(name, age) {
this.age = age ? age : 18;
function sayHi() { console.log("Hi,I'm " + name) };
Object.defineProperty(this, "name", {
set(value) {
if (!value || value.length < 4 || value.length > 12) {
throw Error("值必須是4到12的有效字元");
}
this._name = value;
},
get() { return this._name; }
})
}
let user = new User("sambo");
//使用
user.name = 'sam'; //Uncaught Error: 值必須是4到12的有效字元
Object.getOwnPropertyDescriptor(user, 'name'); //{enumerable: false, configurable: false, get: ƒ, set: ƒ}
?問題:透過上面的示例程式碼可以看出,使用getter/setter 包裝的“私有”屬性
_name
還是會暴露出去。
02、JSON資料
JOSN(JavaScript Object Notation /nəʊˈteɪʃn/)是一種描述物件資料的語法,是一種通用的鍵值資料格式,很多語言都支援,用來儲存、傳輸資料。和Object定義相似,不同的是:
- 屬性名須雙引號包起來的字串。
- 屬性值僅允許字串,數字,陣列,true,false,null或其他(JSON)物件,不支援函式。
let user = {
age: 18,
set name(value) {
if (!value || value.length < 4 || value.length > 12) {
throw Error("值必須是4到12的有效字元");
}
this._name = value;
},
get name() {
this._name ??= "empty";
return this._name;
},
sayHi: function () { console.log('sayHi') }
};
// JSON序列化與反序列化
let userStr = JSON.stringify(user); //'{"age":18,"name":"empty","_name":"empty"}'
let user2 = JSON.parse(userStr);
user2.name = 'sam'; //反序列化後的新物件,沒有了get、set訪問器方法了,只有資料
user2.sayHi(); //Uncaught TypeError: user2.sayHi is not a function
// 透過AJAX請求json資料,更新頁面
const jurl = "https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json";
let request = new XMLHttpRequest();
request.responseType = "json";
request.open("GET", jurl);
request.onload = function () {
let jobj = request.response;
console.log(jobj);
let h1 = document.createElement('h1');
h1.textContent = jobj.squadName;
document.body.appendChild(h1);
}
request.send();
03、Array陣列
Array 陣列是按序號排列的一組資料,索引從0開始,陣列沒有大小限制(不管是否設定了陣列大小),長度可變,資料型別可以任意。總之就是相當自由,沒什麼原則,隨便你搞,也不會報越界的錯誤。
- 透過
array[索引下標]
訪問、設定陣列元素。 - 透過
length
屬性獲取長度。 - 可附加屬性(Array屬於物件),使用“非正整數”作為索引時,會附加屬性,不影其陣列
length
大小。
var arr1 = [1, 2, 3, 4];
var arr2 = new Array(1, 2, 3, 4); //new並指定資料
var arr3 = new Array(3); //指定陣列長度,別相信它,它是會變心的。
console.log(arr3.length); //3
console.log(arr3[6]); //可以越界訪問,返回undefined
arr3[6] = "666";
console.log(arr3.length); //長度為7了
arr3.length = 10; //設定下長度
arr3["name"] = "sam"; //附加了屬性name
console.log(arr3.name); //sam
arr3["12"] = "sam123"; //等同於arr3[12]
?陣列遍歷:
- 索引下標:遍歷索引下標進行訪問。
for (let i = 0; i < arr3.length; i++) { arr3[i] }
for...in
遍歷陣列裡面的所有下標(鍵),包括數字索引、附加屬性Key
。for...each
迴圈遍歷集合的數值、索引下標,只有正常陣列的部分。
?陣列方法/屬性
Array 屬性/方法 | 描述 | 備註 |
---|---|---|
✅靜態屬性/方法 | ||
Array.from() IE? | 建立一個新的、淺複製的陣列例項:Array.from(arrayLike,mapFn?) | Array.from("123") //['1', '2', '3'] |
Array.isArray(arr) | 判斷是否Array,和instanceof Array 差不多 |
Array.isArray([]); //true |
Array.of() IE? | 根據可變引數建立陣列:Array.of(v0,v1,...vN) | Array.of(1,2,3) //[1, 2, 3] |
✅建構函式 | ||
Array() | 建立一個新的 Array 物件:new Array(v0,v1,...vN) 、new Array(len) | new Array(1, 2, 3, 4) |
✅例項屬性/方法 | (Object.prototype.) | |
length | 元素個數 | |
indexOf(v) | indexOf(value,start?):查詢值的索引位置,➡️從前往後,start預設0。 | arr.indexOf(2); |
lastIndexOf(v) | lastIndexOf(value,start?):查詢值的索引位置,⬅️從後往前 | |
find(func) IE? | 查詢符合條件的元素值,findIndex(func) 返回索引 |
同類:findLast()、findLastIndex() |
includes(v) IE? | 判斷是否包含指定的值,返回bool | arr.includes(2); //true |
push(v)、pop() | push 末尾追加元素(n個)並返回長度,pop 末尾移除(1個)並返回其值 |
arr.push('a','b'); |
unshift(v)、shift() | unshift 在頭部插入元素(n個)並返回長度,shift 頭部移除(1個)並返回,同上 |
shift /ʃɪft/ 轉移, 改變 |
copyWithin(i) IE? | 淺複製陣列中的內容,陣列內部的複製、貼上 | copyWithin(target, start, end) |
fill(v,s,e) IE? | 填充指定的值,arr.fill(value, start, end) ,不含end |
arr.fill(0,1,3) //[1, 0, 0] |
keys()/values() | 陣列索引、值的迭代器,及entries() |
|
sort() | 字元排序,注意預設是按字串(碼值)比較排序,可傳入排序函式 | arr1.sort(function(a,b)) |
reverse() | 反轉陣列項的順序 | |
concat(arr) | 合併多個陣列、元素,返回新的陣列,原資料不變。 | arr1.concat(7,["a","b"]) |
slice(start,end?) | 擷取陣列並返回,指定起止位置,不含end,無end則到末尾,原資料不變 | arr1.slice(2) ( slice /slaɪs/ 切片) |
splice() | 刪除、插入和替換:arr.splice(start, deleteCount,...items)items 為待插入資料 |
/splaɪs/移接 |
forEach(func) | 陣列遍歷,forEach(function(element, index, array) |
|
map(func) | 陣列遍歷執行函式,返回每次函式結果組成的陣列 | arr.map(function(v,index)) |
filter(func) | 遍歷查詢,執行查詢函式,返回滿足過濾條件組成的陣列。 | arr.filter(function(v,index)) |
every(func) | 遍歷是否都滿足條件,只有所有項都滿足條件,才會返回true | arr.every((x,i)=>{return x>3;}) |
some(func) | 遍歷是否都存在滿足條件,只要有一項滿足條件,就會返回true。 | arr.some((x,i,arr)=>x>3) |
join() | 把陣列轉換成字串,引數為連線符,預設, |
arr.join('-') //'1-2-3-4-5' |
toString() | 轉換為字串,逗號, 連線 |
|
reduce(func) | 遞迴+迴圈執行函式:每個元素執行回撥,結果作為下一次回撥的引數 | arr.reduce((p, v) => v + p) //求和 |
var arr1=["a","b","c","d"];
console.log(arr1.pop()); //d
console.log(arr1.push("d","e")); //5
arr1 = [13, 24, 51, 3,"6"];
console.log(arr1.sort()); // [13, 24, 3, 51, '6']
function sortN(a,b){
return a-b; // >0則a更大排到b後面
}
console.log(arr1.sort(sortN)); // [3, '6', 13, 24, 51]
var newarr=arr1.concat("7",["a","b"]); //newarr=[3, '6', 13, 24, 51, '7', 'a', 'b']
//splice
var arr=[1,2,3,4];
console.log(arr.splice(0,1)); //[1]
04、Date日期
Date:日期時間物件,建立、獲取日期,日期是一個包含年月日時分秒、及相關時間方法的資料物件。Date 時間基於 Unix Time Stamp,即自 1970 年 1 月 1 日(UTC)起經過的毫秒數。
屬性/方法 | 描述 | 備註 |
---|---|---|
✅靜態屬性/方法 | ||
Date.now() | 獲取當期時間的時間戳 | Date.now(); //1660059491585 |
Date.parse(str) | 解析日期字串,並返回時間戳 | Date.parse('2021-12-1') //1638288000000 |
Date.UTC(year,...) | 獲取指定年月日時分秒的時間戳,引數同建構函式 | |
✅建構函式 | ||
Date() | 建立Date物件的唯一方式,不加new 返回的是字串- 無引數,當期日期 - 年月日時分秒、毫秒,注意monthIndex從0開始 - Unix 時間戳、字串 |
new Date();//當前日期 new Date(2022,10,11,10,1,1) Date(); //當期時間的字串 |
✅例項屬性/方法 | (Object.prototype.) | |
getDate() | 獲取日,還有獲取年、月、日、星期、時、分、秒 | d.getDate() //11 |
setDate(date) | 設定日,還有設定年、月、日、時、分、秒 | d.setDate(12) |
getTime() | 獲取時間戳 | d.getTime() //1668132061000 |
toLocaleString() | 返回日期時間的本地格式化字串 | "2022/11/11 10:01:01" |
toString() | 返回字串 | "Fri Nov 11 2022 10:01:01 GMT+0800 (中國標準時間)" |
toLocaleDateString() | 返回日期的本地格式化字串 | "2022/8/10" |
toLocaleTimeString() | 返回時間的本地格式化字串 | "10:07:05" |
toJSON() | 轉字串,JSON序列化使用 | "2022-08-10T02:14:39.138Z" |
valueOf() | 原始值(時間戳) | 1660097530418 |
const today = new Date();
const birthday = new Date('1995-02-07T03:24:00');
const birthday2 = new Date(1995, 11, 17, 3, 24, 0);
//計算年齡
const v1 = today-birthday; //867998585554 日期相減得到的是時間間隔的毫秒數
const age = Math.floor(v1 /(365*24*60*60*1000)); //27歲
05、Math數學公式
Math 是一個內建物件,擁有一些數學常數屬性和數學函式方法。
靜態屬性/方法 | 描述 | 示例 |
---|---|---|
Math.PI | 圓周率 | 3.141592653589793 |
Math.random() | 隨機數,0到1的小數(不含1) | Math.random() //0.4710000565662491 |
Math.ceil(1.23) | 向上取整 | Math.ceil(1.23); //2 |
Math.floor(1.23) | 向下取整 | Math.floor(1.23); //1 |
Math.abs(x) | 絕對值 | Math.abs(-1); //1 |
Math.max(x1,...xn) | 求最大值,對應的Math.min() 求最小值 |
|
Math.round(x) | 取四捨五入的整數 | Math.round(1.55) //2 |
Math.pow(x, y) | 計算x的y次方 | |
Math.sqrt(x) | 計算平方根 |
❗Math精度:很多 Math 函式都有一個精度,而且這個精度在不同實現中也是不相同的。這意味著不同的瀏覽器會給出不同的結果,甚至,在不同的系統或架構下,相同的 JS 引擎也會給出不同的結果!
06、Map/Set帶鍵集合
由唯一、不可重複Key
值標記的鍵值[key, value]
集合容器Map(IE11),以及由唯一、不可重複value
值[value]
集合Set(IE11)。
?鍵唯一判斷:零值相等演算法,基於===比較,NaN與自身相對,-0、+0相等
型別/屬性/方法 | 描述 |
---|---|
✅Map{[key, value]} | 鍵值對,順序插入,支援任何型別作為建、值 |
Map(...[iterable]) | 建構函式,建立 Map 物件,支援二維陣列、可迭代物件,包括其他map(合併map) |
size | 數量 |
get(key) | 獲取鍵值 |
set(key,value) | 新增/設定鍵值對 |
delete(key) | 刪除鍵值對 |
has(key) | 判斷key是否存在 |
clear() | 清空 |
keys()/values() | 獲取鍵、值的迭代集合 |
entries() | 獲取鍵值[key, value]迭代物件:map.entries().next().value //['sex', 'male'] |
forEach(func) | 執行迴圈迭代:forEach(function(value, key, map) |
✅WeakMap{[key, value]} | 弱引用Map,鍵必須是物件,而值可以是任意的。(Weak /wiːk/ 弱)。鍵(引用物件)被弱保持,沒有被其他地方引用,會被GC回收。Key不可列舉 |
WeakMap() | 建構函式,用法類似Map,沒有迭代相關方法,無size、clear() |
✅Set{key} | 不重複值的集合 |
Set(...[iterable]) | 建構函式,建立Set物件 |
add(obj) | 新增值,其他屬性方法類似Map |
✅WeakSet{key} | 弱引用Set,值必須是物件,如果沒有被引用會被GC回收,不可列舉 |
Object與Map、Set的區別:
Object | Map | Set | |
---|---|---|---|
資料結構 | {name:value,...} |
{key => value, ...} |
{key1, ...keyN} |
預設鍵值 | 有一個原型 | 無-空無一物 | 無-空無一物 |
鍵 | 字串string或symbol | 任意型別,有序(插入順序) | 無 |
Size | 無, 自己計算 | size | size |
迭代 | 無迭代協議,不支援for(of) ,可以用for(in) 列舉屬性 |
可迭代for(of) |
可迭代for(of) |
效能 | 一般 | 鍵值操作,效能良好 | |
序列化 | 支援JSON的序列化方法 | 不支援 | 不支援 |
let map = new Map([[1, "N1"], ["age", 20]]);
map.set(2, "N2"); //{1 => 'N1', 'age' => 20, 2 => 'N2'}
map.forEach((value, key) => { //注意是value在前面
console.log(key + ":" + value); //1:N1 age:20 2:N2
})
console.log(JSON.stringify(map)); //{} 什麼都沒有
let set = new Set([1, 2, 3, "a"]);
console.log(set); //{1, 2, 3, 'a'}
set.forEach((value) => {
console.log(value); //1, 2, 3, a
})
©️版權申明:版權所有@安木夕,本文內容僅供學習,歡迎指正、交流,轉載請註明出處!原文編輯地址-語雀