对象

84 阅读3分钟

对象----你不知道的javascript(上)

七种主要类型:string,number,boolean,null,undefined,object,symbol.

对象的引用可以是myObject.a或者是是myObject[a]形式进行访问。常用myObject.a

  1. 对象的复制

复制分为浅复制和深复制两种。深复制会直接取值;浅复制是直接对属性进行引用。

浅拷贝:

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);
  1. 属性描述符
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..的枚举中
  1. 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实现原理中有涉及到。

  1. 存在性
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()返回一个数组,包含所有属性,无论是否可枚举。这两者都只会查找对象直接包含的属性,不会查找原型链。

  1. 遍历

对于对象,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
  }
};