Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

深入了解js拷贝(赋值与引用) #3

Open
axlroseart opened this issue Aug 6, 2019 · 0 comments
Open

深入了解js拷贝(赋值与引用) #3

axlroseart opened this issue Aug 6, 2019 · 0 comments

Comments

@axlroseart
Copy link
Owner

axlroseart commented Aug 6, 2019

number,string类型都是基本类型,而基本类型存放在栈区,访问时按值访问,赋值是按照普通方式赋值,对象和数组是通过引用来赋值的,所以改变a的同时b也会跟着改变。
引用类型指的是对象。可以拥有属性和方法,并且我们可以修改其属性和方法。引用对象存放的方式是:在栈中存放对象变量标示名称和该对象在堆中的存放地址,在堆中存放数据。

浅拷贝:

先写一个浅拷贝函数,接收一个参数为要拷贝的对象

function shallowClone(o) {
  const obj = {}
  for(let i in o) {
    obj[i] = o[i]
  }
  return obj
}
const obj1 = {
name: 'hiko'
}
const obj2 = shallowClone(obj1)

console.log(obj2) ==> { name: 'hiko' }

但如果拷贝对象是这样的:

const oldObj = {
  a: 1,
  b: [ 'e', 'f', 'g' ],
  c: { h: { i: 2 } }
}

调用shallowClone方法后,对不同类型的属性拷贝及相互干扰结果输出如下:

image

很明显虽然oldObj.c.h被克隆了,但是它还与oldObj.c.h相等,这表明他们依然指向同一段堆内存,这就造成了如果对newObj.c.h进行修改,也会影响oldObj.c.h

深拷贝:

JSON对象parse方法可以将JSON字符串反序列化成JS对象,stringify方法可以将JS对象序列化成JSON字符串,这两个方法结合起来就能产生一个便捷的深克隆.

const newObj = JSON.parse(JSON.stringify(oldObj))

1.他无法实现对函数 、RegExp等特殊对象的克隆
2.会抛弃对象的constructor,所有的构造函数会指向Object
3.对象有循环引用,会报错

比上面这种好一点的:

// 先写个判断函数判断对象类型是否为数据:
function isArray(arr) {
 return Object.prototype.String.call(arr) === '[object Array]'
}
// 具体的拷贝方法
function deepClone(obj) {
 // 返回原有类型
 if(typeof obj !== 'object' && typeof obj !== 'function') {
  return obj
 }
// 判断要拷贝的是数组还是对象
var o = isArray(obj) ? [] : {}
// 遍历递归引用赋值
for (const key in obj) {
        if (object.hasOwnProperty(key)) {
          const element = obj[key]
          // 如果具体属性为对象,则递归调用
          o[i] = typeof element === 'object' ? deepClone(element) : obj[i]
        }
      }
}
return o
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant