对象----你不知道的javascript(上)
七种主要类型:string,number,boolean,null,undefined,object,symbol.
对象的引用可以是myObject.a或者是是myObject[a]形式进行访问。常用myObject.a
- 对象的复制
复制分为浅复制和深复制两种。深复制会直接取值;浅复制是直接对属性进行引用。
浅拷贝:
let obj = { id: 1, name: "andy", msg: { age: 18 } };
//方式一:
object.assign(o,obj);
//方式二:
let o = {};
for (let i in obj) {
o[i] = obj[i];
}
console.log(o);//16
obj.msg.age = 16;
console.log(o);//16
深拷贝:
let obj = { id: 1, name: "andy", msg: { age: 18 }, array: [1, 2, 3, 4] };
function deepcopy(newObj, oldObj) {
for (let k in oldObj) {
let item = oldObj[k];
if (item instanceof Array) {
newObj[k] = [];
deepcopy(newObj[k], item);
} else if (item instanceof Object) {
newObj[k] = {};
deepcopy(newObj[k], item);
} else {
newObj[k] = item;
}
}
}
let res = {};
deepcopy(res, obj);
console.log(res);
- 属性描述符
var myObj = {};
Object.defineProperty(myObj, "a", {
value: 2,
writable: false,
configurable: false,
enumerable: false,
});
console.log(myObj.a);//2
myObj.a = 3;
console.log(myObj.a);//2,不可更改值,严格模式下直接报错typeError
Object.defineProperty(myObj, "a", {
writable: true,
configurable: false,
});//报错typeError,因为配置不可更改,并且配置也不可删除。
//enumerable枚举性,禁止之后,该属性将不会出现在for...in..的枚举中
- Getter 和 Setter
对象的读取时,myObj.a不仅仅是查找名字为a的属性,实际上调用了get操作,同理,赋值时调用了set操作。ES5中采用getter和setter来改写默认操作。
var myObj = {
//给a定义一个getter
get a() {
return 2;
},
};
myObj.a = 3;
console.log(myObj.a); //2
var myObj = {
//给a定义一个getter
get a() {
return this.a_;
},
//给a定义一个setter
set a(val){
this.a_ = val*2;
}
};
myObj.a = 2;
console.log(myObj.a); //4
Object.defineProperty、get、set、getter和setter在Vue实现原理中有涉及到。
- 存在性
var myObj = {
a: 2,
};
console.log("a" in myObj);
console.log("b" in myObj);
console.log(myObj.hasOwnProperty("a"));
console.log(myObj.hasOwnProperty("b"));
in会检查属性是否在对象及其原型链当中;in检查的是属性名。例如数组当中[2,4,5],4 in [2,4,5]会报false,因为数组的属性名是0,1,2,没有4.
而hasOwnProperty只会检查属性是否在对象当中,不会检查原型链。
enumerable枚举属性禁止之后,in和hasOwnProperty都能够确认存在该属性,但for...in...无法便利到该属性。
Object.keys()可以返回一个数组,包含所有可枚举属性;object.getOwnPropertyNames()返回一个数组,包含所有属性,无论是否可枚举。这两者都只会查找对象直接包含的属性,不会查找原型链。
- 遍历
对于对象,for...in...遍历所有属性。遍历属性的值能采用什么方法呢
对于数值索引的数组,可以用for循环遍历值,for(let i=0;i<array.length;i++),array[i]即可访问。
forEach、every、some、map、filter可接受一个回调函数并将其应用至数组的每个元素上。
let a = [1,2,3,4,5]
//forEach无返回值,直接对item进行操作。
a.forEach((item)=> 对每个item执行操作);
//其他都有返回值
let res1 = a.every((item) => item > 2);
console.log(res);//false;
let res2 = a.every((item) => item > 2);//true
let res3 = a.filter((item) => item > 2);//[3,4,5]
let res4 = a.map((item) => item * 2);//[2,4,6,8,10]
针对于对象,for...of..可用来直接遍历属性值。
let a = [1, 2, 3, 4, 5];
for (let i of a) {
console.log(i);
}
//1
//2
//3
//4
//5
for...of...首先会被访问对象请求一个迭代器对象,然后通过迭代器对象的next方法来遍历所有返回值。
一、类
当需要提出vehicle和car类时,可以将载人、引擎这些基本所有交通工具都包含的东西放在vehicle中定义;之后,让car继承vehicle这个基础定义就行。但在实例中每辆车都有它独特的车牌号,实例化后会有共同的方法,也会有各自的独特信息。
类实例是由特殊的类方法构造的,被称为构造函数。其任务就是初始化实例所需要的所有信息。
class CoolGuy {
constructor(trick) {
this.specialTrick = trick;
}
showOff() {
console.log(this.specialTrick);
}
}
let Joe = new CoolGuy("jump");
Joe.showOff();//jump
二、继承
class Bus extends Vehicle();
在类构造函数当中使用super调用父类构造函数。
class Bus extends Vehicle{
constructor(){
super();
console.log(this instanceof Vehicle)//true
}
};