數(shù)據(jù)類型與對象
對于JS中的數(shù)據(jù)類型植酥,其本質(zhì)都是基于各自的對象類進行創(chuàng)建的劳淆,因此如果我們可以通過修改這個對象類的原型來對某個數(shù)據(jù)類型整體都進行修改
數(shù)據(jù)類型對象
Number
數(shù)字哈肖,例如我們給數(shù)字類型都添加一個方法判斷是否為正數(shù):
Number.prototype.isPos = function() {
return this > 0;
}
let b = 1;
b.isPos();
// true
Boolean
String
RegExp
Array
Function
參考
https://www.runoob.com/jsref/jsref-obj-array.html
對象API
Object.create
創(chuàng)建對象腾它,第一個參數(shù)指定對象原型趾唱,第二個參數(shù)為對象本身姻报,舉例:
a = {x:1, y:2}
b = Object.create(a, {})
b.__proto__ === a
// true
Object.setPrototypeOf
設置原型兜辞,舉例:
let a = {};
let b = {};
console.log(a.__proto__ === Object.prototype) // true
Object.setPrototypeOf(a, b);
// 將a的原型指向b
console.log(a.__proto__ === Object.prototype) // false
console.log(a.__proto__ === b) // true
Object.getPrototypeOf
查看原型,舉例:
Object.getPrototypeOf({});
// {}
Object.getOwnPropertyDescriptor
獲取對象當中指定屬性的特征陨囊,舉例:
let a = {x:1};
console.log(Object.getOwnPropertyDescriptor(a, "x"));
// { value: 1, writable: true, enumerable: true, configurable: true }
// 幾個屬性分別表示:值弦疮、是否可修改夹攒、是否可遍歷蜘醋、是否可以修改屬性特征
Object.defineProperty
定義、修改屬性特征咏尝,舉例:
let a = {};
Object.defineProperty(a, "x", {
value: 1,
writable: true,
enumerable: false
})
a.x = 2;
console.log(a.x)
// 2
console.log(Object.keys(a));
// []
可以看出屬性x
可修改压语,但不可遍歷
注:
如果定義的屬性設置了訪問器,則不能設置value
和writable
屬性编检,舉例:
let o = {};
Object.defineProperty(o, "a", {
enumerable: true,
configurable: true,
// 如果設置value或writable屬性會報錯
set(val) {
this._a = val;
console.log(val);
},
get() {
return this._a;
}
});
console.log(o.a);
o.a = 100;
console.log(o.a);
// undefined
// 100
// 100
Object.preventExtensions
不允許對象添加屬性胎食,舉例:
let a = {};
a.x = 1
Object.preventExtensions(a);
a.y = 2;
console.log(Object.keys(a));
// [ 'x' ]
可以看出設置不允許添加屬性以后,屬性y
就沒有被添加進去了
注:
可以通過Object.isExtensible
查看對象是否允許添加屬性
Object.seal
封閉屬性允懂,不允許添加厕怜、修改、重新定義屬性(configurable變成false)
注:
可以通過Object.isSealed
查看對象是否凍結
Object.freeze
對象凍結蕾总,無法改變粥航、添加、刪除對象內(nèi)容(writable生百、configurable都變成false)
注:
可以通過Object.isFrozen
查看對象是否凍結
Object.keys()/Object.values()
訪問對象下所有可迭代的key
/value
递雀,舉例:
a = {x:1, y:2}
Object.keys(a)
// ["x", "y"]
Object.is
判斷對象是否為某個類型,舉例:
Object.is("aaa", NaN)
注:
NaN
類型需要用Number.isNaN
或者Object.is
來判斷
Object.assign
將后面幾個對象的內(nèi)容合并到第一個對象里(重復屬性名蚀浆,后面的會覆蓋前面的)缀程,舉例:
console.log(Object.assign({x:1}, {y:2}))
// { x: 1, y: 2 }
我們可以用該方法實現(xiàn)淺拷貝,舉例:
let a = {x:1};
let b = a;
let c = Object.assign({}, a);
// 將a合并到空對象里市俊,從而實現(xiàn)淺拷貝
a.x = 2;
console.log(b.x, c.x);
// 2 1
可以看到此時c和a并不是同一個對象
對象操作
變量命名key
如果希望key
的值是由變量決定杨凑,則可以通過[變量]
來實現(xiàn),舉例:
a = "aaa";
b = {
[a]: 1
}
console.log(b)
遍歷可迭代對象
遍歷key
a = {x:1, y:2};
for(let k in a) {
console.log(k);
}
// x
// y
遍歷數(shù)組時摆昧,獲取的則是下標撩满,舉例:
a = ["a","b","c","d"];
for (let k in a){
console.log(k);
}
// 0
// 1
// 2
// 3
遍歷value
a = ["a","b","c","d"];
for (let v of a){
console.log(v);
}
// a
// b
// c
// d
instanceof
判斷是否是某個類實例(本質(zhì)是看是否prototype是否在其原型鏈上),舉例:
[] instanceof Array
hasOwnProperty
當前對象是否含有某個屬性(不包括原型鏈上的)据忘,舉例:
let a = {x:1};
a.__proto__.y = 1;
console.log(a.hasOwnProperty("x")) // true
console.log(a.hasOwnProperty("y")) // false
attr in o
當前對象是否含有某個屬性(包括原型鏈)鹦牛,舉例:
let a = {x:1};
a.__proto__.y = 1;
console.log("x" in a) // true
console.log("y" in a) // true
訪問器
在對象中當要訪問某個屬性時,可以進行自定義操作勇吊,舉例:
let a = {
data: {
x: 1
},
// 當設置x值的時候觸發(fā)
set x(val) {
console.log("將x設置為:", val);
this.data.x = val;
},
// 當獲取x值的時候觸發(fā)
get x() {
console.log("獲取x的值");
return this.data.x;
}
}
a.x = 100;
console.log(a.x);
// 將x設置為: 100
// 獲取x的值
// 100
類
定義
ES6提供了類相關的關鍵字用于創(chuàng)建里曼追,主要有:class
(定義類)、constructor
(構造器)汉规、extends
(繼承)礼殊、super
(父類)驹吮,static
(定義靜態(tài)屬性/方法)舉例:
class User {
constructor(name, pwd) {
// 構造方法
this.name = name;
this.pwd = pwd;
}
showName() {
// 直接輸入方法名定義方法
console.log(this.name);
}
static showRule() {
// 定義靜態(tài)方法,可以從類直接調(diào)用而無需實例化
console.log("this is User rule");
}
static rule = "this is rule";
// 定義靜態(tài)屬性晶伦,如果報錯可能是瀏覽器版本不支持碟狞,建議換成最新chrome嘗試
}
class Vip extends User {
// 繼承父類
constructor(name, pwd, level) {
super(name, pwd);
// 調(diào)用父類構造方法
this.level = level;
}
showPwd() {
console.log(this.pwd);
}
showLevel() {
console.log(this.level);
}
}
console.log(User.rule);
User.showRule();
// 直接從類調(diào)用靜態(tài)方法
let user = new Vip("aaa", "111", "1");
user.showName();
user.showPwd();
user.showLevel();
- 也可以通過直接在類中通過賦值來定義屬性成員,舉例:
class A {
// 給實例設置私有成員婚陪,等價于在constructor中執(zhí)行this.x = 1
x = 1
y = {a: 1}
// 設置靜態(tài)屬性(@babel/plugin-proposal-class-properties里設置了關于這種語法的處理)
static z = {a: 1}
}
let a = new A();
a.y.a = 2
A.z.a = 2
let a2 = new A();
console.log(a2.y.a);
console.log(A.z.a);
私有屬性
前面加#
即可族沃,私有方法可以通過定義私有屬性的值為函數(shù)即可,舉例:
class A {
#a = () => {};
}
深拷貝/淺拷貝
淺拷貝示例
a = {x:1};
// 實現(xiàn)淺拷貝a
// 第一種
b = { x: a.x };
// 第二種
b = {};
for (let key in a) {
b[key] = a[key];
}
// 第三種
b = { ...a };
// 第四種
b = Object.assign({}, a);
深拷貝示例
- 通過JSON序列化:
let o = {x:1};
let b = o
b === o
// true
let json = JSON.stringify(o)
let deepCopyO = JSON.parse(json)
deepCopyO === o
// false
- JSON序列化只能操作基本類型泌参,對于非基本類型脆淹,可以通過遞歸淺拷貝來實現(xiàn)
- 實際開發(fā)中建議使用
lodash
相關庫來進行深拷貝操作
lodash參考:
https://www.npmjs.com/package/lodash.clonedeep
https://github.com/lodash/lodash/tree/4.5.0-npm-packages/lodash.clonedeep
反射
參考:http://tech.dianwoda.com/2017/08/09/jsde-fan-she-xue-xi-he-ying-yong/