原型模式--如何实现深拷贝

153 阅读2分钟

语言: Javascript

在日常的开发过程中,我们很少会使用到原型模式。但是这一模式是JavaScript实现面向对象编程的基础,在最新的 ES6 语法中,class的实现也是基于原型模式,通过语法糖的改造,让我们更为简便的实现类。

定义一个类

function Dog(name, age) {
	this.name = name;
    this.age = age;
}
Dog.prototype.eat = function() {
	console.log('狗吃肉骨头');
}
//生成实例,调用原型方法
const dog = new Dog();

console.log(dog.name);// 输出: dd
dog.eat();// 输出: 狗吃肉骨头

//直接生成一个实例,调用原型方法
const doaa = {name: 'ff', age: 2};
console.log(doaa.name);// 输出: ff
doaa.eat(); // 输出: dog.eat is not a function

通过以上的代码我们可以发现,通过构造函数生成的实例会调用定义在原型上的方法,直接生成的实例则会报错。这是因为通过构造函数生成的实例,未在实例本身找到方法的时候,会向上从原型中寻找。

原型模式在实践中的运用

在日常开发中我们会很少用到这个设计模式,因为作为语言的基础功能,他已经被整合到语言的标准库和各个框架之中了。但是在外出面试时,考官会经常出原型链相关的题目,以考察你对js语言的掌握程度。

对象的深拷贝

使用JSON.stringify
const dog = {
	name: 'dd',
    age: '2',
    sex: 'boy'
}

const dogStr = JSON.stringify(dog);
const dogCopy = JSON.stringify(dogStr);

dogCopy.name = 'sss';
console.log('原对象的名字:', dog.name); // 输出 dd
console.log('拷贝对象的名字:', dogCopy.name); // 输出 sss

以上方法存在局限性,无法处理 function 和 正则表达式等,它必须是一个严格的 JSON 对象。

使用递归

function deepClone(obj) {
	// 如果是值类型 或者 null,直接return
    if(typeof obj !== 'object' || obj === null) {
    	return obj;
   	}
   // 定义结果对象
   let copy = {};
   // 如果对象是数组,则定义数组
   if(obj.constructor === Array) {
   		copy = [];
   }
   //遍历对象的key
   for(const key in obj) {
  		//如果key是自有属性
        if(obj.hasOwnProperty(key)) {
        	copy[key] = deepClone(obj[key]);
        }
    }
    return copy
}

核心思想:调用深拷贝方法,如果属性为值类型,则直接返回;若属性为引用类型,则递归遍历。