javascript中的对象相关方法一

124 阅读5分钟

前言

最近工作有点空闲时间,想整理下之前学过的对象中的相关方法的使用,因为对象中的方法太多了,梳理的过程可以加深自己的理解。

创建对象

平常我们创建对象都是使用字面量的形式,其实创建对象还可以通过new Object()的形式创建,这两种创建方式是一样的。

1.通过new Object()创建
var obj = new Object()  obj.name = "aaa"  obj.age = 18
2. 字面量形式
var obj = { name: "aaa", age: 18 }

delete对象属性

1.delete用来删除对象的属性,删除成功后返回true。用delete删除一个不存在的属性时也不报错,而且返回true。

const obj = { age: '18', address: '2344' }
console.log(delete(obj.sss));  // true

2.delete无法删除继承的属性,例如toString属性,即使delete返回true,该属性还是没有被删除可以被读取。

const obj = { age: '18', address: '2344' }
console.log(delete(obj.toString)); // true
console.log("toString" in obj) // true

3 .delete删除一个数组元素,会形成空位,并且不会影响数组的length值

const arr = [2,3,4,5,6]
delete(arr[0])  
console.log(arr);  // [ <1 empty item>, 3, 4, 5, 6 ]
console.log(arr.length);  // 5

Object()

将任意值转为对象,如果参数为空(或者为undefinednull),Object()返回一个空对象;如果参数是一个对象,它总是返回该对象,即不用转换。

var arr = [];
arr === Object(arr); // true

可以用此方法封装一个判断变量是否为对象的方法:

function isObject(value) {
  return value === Object(value);
}
isObject([]) // true
isObject(true) // false

Object.seal()

禁止对象配置和删除属性。

Object.freeze()

冻结对象,不允许修改现有属性。

Object.preventExtensions()

禁止对象继续添加新的属性

in/for in/for of

in操作符用来判断某个属性是否在对象或者对象的原型上,包括不可遍历属性。 for in操作符用来遍历对象的所有可遍历属性,包括继承属性。继承的toString属性不会被遍历是因为默认不可遍历。 for of操作符不能用来遍历普通对象,只可以遍历可迭代对象,什么是可迭代对象以后我会详细说。

const obj = { age: '18', address: '2344' }
console.log('address' in obj);  // true
for (const k in obj) {
    console.log(k);  //  age address
}

hasOwnProperty

判断对象中是否有这个属性,包括不可遍历属性,不包括继承属性。

const obj = { age: '18', address: '2344' }
console.log(obj.hasOwnProperty('address'));  // true
console.log(obj.hasOwnProperty('toString')); // false

这个方法可以和for in结合使用

const obj = {xxxx}
for (const k in obj) {
	if (obj.hasOwnProperty(k)) { // 这里可以去除掉可遍历的继承属性
		// 逻辑处理......
	}
}

Object.getOwnPropertyNames()

返回一个字符串数组,数组成员是对象键名,不包括继承属性,包括不可遍历属性。

Object.keys()

返回一个字符串数组,数组成员是对象键名,不包括继承属性,不包括不可遍历属性。

Object.getOwnPropertyDescriptors()

Object.getOwnPropertyDescriptor(obj, "name") // 获取某一个属性的属性描述符
Object.getOwnPropertyDescriptors(obj) // 获取对象的所有属性描述符

Object.defineProperty()

在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

# 接收三个参数
Object.defineProperty(obj, prop, descriptor)
1.obj要定义属性的对象 2.prop要定义或修改的属性的名称或Symbol 3.descriptor定义或修改的属性描述符

# 属性描述符
value:属性的value值,读取属性时会返回该值,修改属性时会对其进行修改,默认值为undefined
Writable:表示是否可以修改属性的值
Configurable: 属性是否可以通过delete删除属性,是否可以修改它的特性
Enumerable:属性是否可以通过for-in或者Object.keys()返回该属性
get:获取属性时会执行的函数。默认为undefined
set:设置属性时会执行的函数。默认为undefined

# 属性描述符注意项
1.configurable:false时,还是可以把writable由true改为false,不可以由false改为true
2. 取值函数get不能接受参数,存值函数set只能接受一个参数
3. get与set属性和writable: true value属性不能同时存在

当使用Object.defineProperty()方法定义对象属性时,属性描述符的默认值都为false

const obj = {}
Object.defineProperty(obj, 'age', { value: 18 })
console.log(obj); // {},因为属性描述符中Enumerable为false,不可遍历
console.log(Object.getOwnPropertyDescriptor(obj, 'age')); 
// { value: 18, writable: false, enumerable: false, configurable: false }

然而当使用字面量形式定义对象属性时,属性描述符的默认值都为true

const obj = {}
obj.age = 18
console.log(obj);  // { age: 18 }
console.log(Object.getOwnPropertyDescriptor(obj, 'age'));
// { value: 18, writable: true, enumerable: true, configurable: true }

Object.defineProperties()

可以同时定义多个属性。

const obj = {}
Object.defineProperties(obj, {
    name: {
        value: '哈哈'
    },
    age: {
        value: 18
    }
})
console.log(Object.getOwnPropertyDescriptors(obj));

// 打印结果如下
{
  name: {
    value: '哈哈',
    writable: false,
    enumerable: false,
    configurable: false
  },
  age: {
    value: 18,
    writable: false,
    enumerable: false,
    configurable: false
  }
}

Object.getPrototypeOf()

获取对象的原型。

const obj = {} // 相当于 const obj = new Object()
console.log(Object.getPrototypeOf(obj) === obj.__proto__); // true
console.log(Object.getPrototypeOf(obj) === Object.prototype); // true

Object.setPtototypeOf()

Object.setPtototypeOf(newObj, obj) 就是将obj对象作为newObj对象的原型。

const obj = {}
const newObj = {}
Object.setPrototypeOf(newObj, obj)
console.log(Object.getPrototypeOf(newObj) === obj); // true

instanceof

用于检测构造函数的pototype,是否出现在某个实例对象的原型链上,这个instanceof的原理以后会详细讲。

console.log(stu instanceof Student) // 检测Student的pototype是否在stu对象的原型链上

class Person {
  constructor(age) {
    this.age = age
  }
}
const ss = new Person()
console.log(ss instanceof Person); // true
console.log(ss instanceof Object); // true

Object.create()

我忘了是干啥的了,但是会使用,参数不能为空。还有这个方法在以后讲的继承中会用到。 这个方法好像是以传入的参数作为创建的对象的原型,并返回一个空对象。

const obj = { name: "why", age: 18}
const info = Object.create(obj) // obj对象是info对象的原型
console.log(info); // {}
console.log(Object.getPrototypeOf(info) === obj); // true

// 传入的参数是null时有点特殊
let obj = Object.create(null) // {},就是生成了一个空对象.该对象没有valueOf和toString方法。
Object.create(null) instanceof Object // false,因为返回的空对象的原型是null,已经处于原型链最顶层了

isPrototypeOf

用于检测某个对象,是否出现在某个实例对象的原型链上。

var obj = { name: "why", age: 18}
var info = Object.create(obj)
console.log(obj.isPrototypeOf(info)) 

总结

上述都是Object常用的一些方法,有一些没使用过,有一些经常使用,比如Object.create()。后面应该还有继承,浅拷贝,深拷贝,判断对象是否相同等一些内容。