前端面试题(第三弹)——js对象的基本方法和深浅拷贝

一、 js对象(object)

1.创建对象的两种方式

第一种

let person = new Object();
person.name = "dabing";
person.age = 23;
person.sayName = function () {
	console.log(this.name)
}

第二种

let person = {
   name:"xiaowang",
   age:22,
   sayName () {
   console.log(this.name)
  }
}

2. 对象属性的类型

1.configurable:属性是否可以通过delete删除,默认值为true。
2.enumberable:属性是否可以通过for in 进行循环返回,默认值为true。
3.writable:属性是否可被修改,默认值为true。
4.value:属性实际的值,默认为undefined。

//要修改属性的默认特性,就必须使用Object.defineProperty()方法
let person = {}
Object.defineProperty(person, "name", {
	writable: false,     //设置person的name属性不可修改
	value:"xiaowang"
})

// defineProperty()  方法接受三个参数 第一个是要修改的对象,第二个是对象的属性,
//                   最后一个参数是一个对象里面包含了
//                   四个属性configurable、enumberable、writable、value
                
console.log(person.name);   //"xiaowang"
person.name = "dabing"
console.log(person.name)  //"xiaowang"

3. 访问器属性

访问器属性有四个属性类型,也是使用Object.defineProperty() 进行定义修改,
1.configurable:属性是否可以通过delete删除,默认值为true。
2.enumberable:属性是否可以通过for in 进行循环返回,默认值为true。
3.get(){}; 读取属性,默认undefined。
4.set(){}; 设置属性,默认undefined。

访问器属性对于没有接触过的人来说有点难理解,怎么区分数据属性与访问器属性呢?

如下例子,我们一般在设置访问器属性的时候,会给属性在前面或者后面加上下划线(属于是约定俗成),以表示私有变量,在js中这是伪私有。
设置完伪私有变量之后,一般情况下我们是不希望直接访问这个属性的,所以我们给book再定义一个“year”,我们会直接访问这个year ,这个year就是访问器属性,而不是去访问_year,
在通过Object.defineProperty()方法中,设置get、set也不是必要的。可以根据实际场景进行调整。

let book = {
  _year:2017,
  edition: 1
}

Object.defineProperty(book, "year", {
    get() {
    	return this._year;
    }set(newValue) {
       if(newValue > 2017) {
			this._year = newValue;
			this.eidtion += newValue - 2017;
       }
    }
})
book.year = 2018
console.log(book.edition)  //2

//另外有定义多个属性的方法Object.defineProperties({

	year_:{
    value:2017
   },
	edition:{
    value:1
    },
    year:{
	get() {
	 return this.year_;
	}, 
	set(newValue) {
       if(newValue > 2017) {
			this._year = newValue;
			this.eidtion += newValue - 2017;
       }
	}
})
//读取属性的特性的方法Object.getOwnPropertyDescriptor(对象,属性)
//访问对象所有属性特性的方法Object.getOwnPropertyDescriptors(对象)

二、基本类型和引用类型

基本类型的数据包括number、string、boolean、null、undefined ———基本数据类型是值传递
引用数据类型 Object {} 、[] 、function(){} 、Date 、RegExp ———引用数据类型是地址传递

var number = 23
var a = number
a = 20
console.log(number+a)    //43  栈内存  会开辟新地址

var obj ={ 
	name:"xiaowang",
	age:23
}
var b = obj;
b.name = "dabing"
console.log(obj)  //{name: 'dabing', age: 23}  堆内存 b会指向obj的内存地址 修改的是同一个对象

三、 深浅拷贝

1. 深浅拷贝定义解释

深浅拷贝就像上面举的例子一样,浅拷贝就是指Object的直接复制,修改一个值另一个也跟着变化,两个指向同一个内存地址,深拷贝指的是我们对于Object的拷贝,可以实现两个对象互不影响,像基本数据类型那样。

2. 实现深拷贝的方法

> JSON.parse(JSON.stringify(obj))

obj = {name:"aa"}
var b = JSON.parse(JSON.stringify(obj))
b.name = "bb"
console.log(obj)    // {name: 'aa'}
console.log(b)      // {name: 'bb'}

!!!注意:

JSON.parse(JSON.stringify(obj)) 是最简单的实现方式,但是有一些缺陷:
对象的属性值是函数时,无法拷贝。
原型链上的属性无法拷贝
不能正确的处理 Date 类型的数据
不能处理 RegExp
会忽略 symbol
会忽略 undefined

> 实现一个 deepClone 函数 (深拷贝,递归)

function deepClone (obj) {
	if(typeof obj != 'object') {
		return obj
	}
	let newObj = obj.constructor === Array ? [] : {}
	for (let i in obj ) {
		if(obj[i] instanceof Object) {
		     newObj[i] = deepClone(obj[i])
		}else{
		     newObj[i] = obj[i];
		}
	}
	return newObj;
}
var obj = {name:"wang ",age:22}
var obj2= deepClone(obj)
obj2.name = "bing"
console.log(obj2)    //  {name: 'bing', age: 22}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iiiiiiiice

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值