深拷贝和浅拷贝相关

浅拷贝

  • 只拷贝一层
    • 如果拷贝的是简单数据类型, 它传递的是值, 有自己的内存空间
    • 如果拷贝的是复杂数据类型, 它传递的是引用
  • 实现浅拷贝方式

方式一 : 封装函数

function simpleClone(obj) {
  let newObj = {}
  for (let key in obj) {
    newObj[key] = obj[key]
  }
  return newObj
}
let obj = { a: { b: 1 }, name: 'zs', say: `funtion(){alert('hello')}` }
let newObj = simpleClone(obj)
console.log(obj)
newObj.a.b = 33
newObj.name = 'ls'
newObj.say = function() {
  alert('yell')
}
console.log(obj)
//{ a: { b: 1 }, name: 'zs', say: "funtion(){alert('hello')}" }
// { a: { b: 33 }, name: 'zs', say: "funtion(){alert('hello')}" }

方式二 : Object.assign()

Object.assign( target , … , source) 把源对象的属性复制给target目标对象

如果源对象嵌套的层级深 , 就是浅拷贝 ,只拷贝一层的引用

如果源对象就一层嵌套 , 就是深拷贝 ,拷贝的是值

//浅拷贝
let obj = { a: { b: 1 }, name: 'zs', say: `funtion(){alert('hello')}` }
let newObj = Object.assign({}, obj)
console.log(obj)
newObj.a.b = 33
newObj.name = 'ls'
newObj.say = function() {
  alert('yell')
}
console.log(obj)
//{ a: { b: 1 }, name: 'zs', say: "funtion(){alert('hello')}" }
// { a: { b: 33 }, name: 'zs', say: "funtion(){alert('hello')}" }

深拷贝

  • 拷贝多层-
  • 实现深拷贝方式

方式一 : 手动复制

方式二 : 使用 Object.assign()

只适用于对象只有一层

let obj = { a: 1, b: { d: 4 }, c: 3 }
let newObj = Object.assign({}, obj)
console.log(obj)
newObj.a = 33
newObj.b.d = 22
console.log(obj)
//{ a: 1, b: { d: 4 }, c: 3 }
// { a: 1, b: { d: 22 }, c: 3 }

方法三 : 转成json格式再转会对象

缺点: 会丢失对象的constructor, 就是深拷贝出来的对象,无论之前构造函数是什么,拷贝后都会变成 object ; 复制的function会消失
只适用于 : 对象只有纯数据

var obj1 = { a: { b: 10 } };
var obj2 = JSON.parse(JSON.stringify(obj1));
obj2.a.b = 20;
console.log(obj1);
// { a: { b: 10 } } <-- 沒被改到
console.log(obj2);
// { a: { b: 20 } }
console.log(obj1 === obj2);
// false
console.log(obj1.body === obj2.body);
//false

方式四: 回调函数

function deepClone(initObj, finalObj) {
  let obj = finalObj || {}
  for (var key in initObj) {
    var prop = initObj[key]
    if (prop === obj) { //避免回调自己,形成死循环
      continue
    }
    if (typeof prop === 'object') {
      obj[key] = prop.constructor === 'Array' ? [] : {}
      arguments.callee(prop, obj[key])
    } else {
      obj[key] = prop
    }
  }
  return obj
}
let obj = { a: { b: 1 }, name: 'zs', say: `funtion(){alert('hello')}` }
let newObj = deepClone(obj)
console.log(obj)
newObj.a = [1, 2, 3]
newObj.name = 'lss'
console.log(obj)
//{ a: { b: 1 }, name: 'zs', say: "funtion(){alert('hello')}" }
// { a: { b: 1 }, name: 'zs', say: "funtion(){alert('hello')}" }

方式五 : 使用 Object.create()

function deepClone(initObj, finalObj) {
  let obj = finalObj || {}
  for (let key in initObj) {
    let prop = initObj[key]
    if (prop === obj) {
      continue
    }
    if (typeof prop === 'object') {
       obj[key] = (prop.constructor === 'Array') ? [] : Object.create(prop)
    } else {
      obj[key] = prop
    }
  }
}
let obj = { a: { b: 1 }, name: 'zs', say: `funtion(){alert('hello')}` }
let newObj = deepClone(obj)
console.log(obj)
newObj.a = [1, 2, 3]
newObj.name = 'lss'
console.log(obj)
//{ a: { b: 1 }, name: 'zs', say: "funtion(){alert('hello')}" }
// { a: { b: 1 }, name: 'zs', say: "funtion(){alert('hello')}" }

new和 Object.create的区别

new

//new 实例化构造函数/类
//做了四件事情
//1. 创建一个空对象
//2.this指向这个空对象
//3. 执行构造函数,给属性添加属性
//4. 返回该对象

Object.create(proto, [propertiesObject])

创建一个新对象,使用 现有的对象 来提供新创建的对象的proto

proto 是新创建对象的原型

propertiesObject 添加到新对象上作为可枚举的属性(自身身上的属性,不是原型链上的)

function Person(name, age) {
  this.name = name
  this.age = age
}
Person.prototype.say = function() {
  console.log('say hello')
}

let a = new Person()
let b = Object.create(Person.prototype)
 console.log(a) //Person { name: undefined, age: undefined }
 console.log(b) //Person {}  b的构造函数F()在Object.create()内部被隐藏起来了,所以b继承不到构造函数的属性
 //但由于 新创建对象和现有对象的原型是一个,所以b实例有say方法
 b.say() //say hello

//new 构造函数, 实例可以继承构造函数的属性和原型上的方法
//Object.create() 创建的实例 不能继承构造函数的属性,但因为原型是一个,所以有方法

配置可枚举属性

function Person(name, age) {
  this.name = name
  this.age = age
}
Person.prototype.say = function() {
  console.log('say hello')
}

let a = new Person()
let b = Object.create(Person.prototype)

//配置新创建对象的可枚举属性
let c = Object.create(Person.prototype, {
  name: {
    value: 'zsy',
    writable: true,
    configurable: true,
    enumerable: true
  },
  sex: {
    enumerable: true,
    get: function() {
      return 'hello sex'
    },
    set: function(val) {
      console.log('set value:' + val)
    }
  }
})
console.log(c) //Person { name: 'zsy', sex: [Getter/Setter] }

继承

  • 原型链继承
function Person(name, age) {
  this.name = name
  this.age = age
}
Person.prototype.say = function() {
  console.log(`hello,${this.age}${this.name}`)
}
let p = new Person('zs', 10)
console.log(p) //Person { name: 'zs', age: 10 }

p.say()   // hello,10的zs
  • call/apply借用继承
function Person(name, age) {
  this.name = name
  this.age = age
}
Person.prototype.say = function() {
  console.log('hello')
}
function Child(name, age, skill) {
  Person.call(this, name, age)
  this.skill = skill
}
let c = new Child('ls', 16, 'play game')
console.log(c) //Child { name: 'ls', age: 16, skill: 'play game' }
  • 混合继承
function Person(name, age) {
  this.name = name
  this.age = age
}
Person.prototype.say = function() {
  console.log('hello')
}
function Child(name, age, skill) {
  Person.call(this, name, age)
  this.skill = skill
}
//继承方法
//方式一
// Child.prototype = Person.prototype
//方式二
Child.prototype = Object.create(Person.prototype)
Child.prototype.constructor = Child

Child.prototype.eat = function() {
  console.log('eat food')
}

let c = new Child('ls', 16, 'play game')
console.log(c) //Child { name: 'ls', age: 16, skill: 'play game' }
c.say() //hello
console.log(Child.prototype.constructor)  //Child
  • class继承
class Person {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  say() {
    console.log('我是父级的函数')
  }
}
class Child extends Person {
  constructor(name, age, skill) {
    super(name, age)
    this.skill = skill
  }
  say() {
    super.say()
    console.log('我是继承父级的函数')
  }
}
let c = new Child('zs', 13, 'play game')
console.log(c)
c.say()
//Child { name: 'zs', age: 13, skill: 'play game' }
// 我是父级的函数
// 我是继承父级的函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值