js 对象之间的关系仔细分析是有着环环相扣的关系,今天来说说继承吧
构造函数
首先来看一个构造函数
function Person(name) {
this.name = name
this.age = 20
this.hobby = function() {
console.log('篮球')
}
}
// 对象的比较方法 1.值 2.内存地址
let zhangsan = new Person('张三')
let lisi = new Person('李四')
console.log(zhangsan.hobby === lisi.hobby) //false
new 开辟了新的内存地址,值相同,耗费性能; 如何节约内存空间? 请看下面的原型继承
原型继承
function Person(name) {
this.name = name
this.age = 20
}
Person.prototype.hobby = function() {
console.log('篮球')
}
Person.prototype.fn = function() {
// ...
}
let zhangsan = new Person('张三')
let lisi = new Person('李四')
console.log( Person.prototype === zhangsan.__proto__)
console.log(zhangsan.hobby === lisi.hobby) //true
功能空间原型: 当存在公共功能或变量时,可以放在原型上,原型是公用的,原型中的this也是指向实例化对象,也就是说在原型中统一可以拿到Person中的name、age
上面的代码看起来好像解决了性能问题,但是也不是完全适用的,比如说
function Dad(name, age) {
this.name = name
this.age = age
this.money = "10000"
}
Dad.prototype.fn = function() {
console.log('fn')
}
function Son(name, age) {
Dad.call(this, name, age)
this.sex = 'man'
}
// zhangsan.fn() 报错
// let zhangsan = new Son("zhansgan", 20)
console.log(zhangsan.money) //10000
Dad.prototype = Son.prototype // 引用地址一样
Son.prototype.fn = function() {
console.log('重写fn')
}
let zhangsan = new Son()
// console.log(zhangsan.fn) 重写fn
let zhangyi = new Dad()
// console.log(zhangyi.fn) 重写fn 父类的fn被改变了
//复杂数据类型传值 地址之间有引用关系,相互影响
// 简单数据类型传值 新开辟内存地址
let a = 10
let b = a
b = 20
console.log(a) // 10
当遇到复杂类型时就不再适用了,如何解决请接着往下看
深拷贝
先来介绍下深拷贝
深拷贝
序列化:
1.先转换为json字符串,变成基本类型就会开辟新的内存空间
2.再转换为对象 实现方式:JSON.parse(JSON.stringify(obj))
缺点: 对象中出现function 、 undefined,会被丢失 只能拷贝一级,对象嵌套则无效
let Dad = {
name: 'zhangsan',
age: 50,
}
let Son = JSON.parse(JSON.stringify(Dad))
Son.name = 'xiaozhang'
console.log(Dad.name) //zhangsan
console.log(Son.name) //xiaozhang
那我们就手动写一个方法实现深拷贝
1.新生成一个对象,用来拷贝,开辟新的引用地址
2.判断这个对象是否是array,因为array也属于对象,如果是就新建一个数组,如果不是
就新建一个对象
3.遍历循环每一项并拷贝,因为for in 循环的特性,会遍历循环对象上所有的属性包括
原型上的,但是我们只需要自身的,所以就用hasOwnProperty进行判断
4.如果是普通类型就直接复制,如果是对象就需要递归循环
function deepCopy(obj) {
let newObj = Array.isArray(obj) ? [] : {}
for(key in obj) {
if(obj.hasOwnProperty(key)) {
if(typeof obj[key] === 'object') {
newObj[key] = deepCopy(obj[key])
}else {
newObj[key] = obj[key]
}
}
}
return newObj
}
当然,js中还有很多种继承方式,原生的继承方式自身也存在着一些局限,目前由于ES6运用的比较广泛,extends更好的解决了原生的局限性,感兴趣的小伙伴也可以去研究一下哦