这咋还没完没了呢?我们之前使用原型+构造函数混合模式创建对象时是这样子写的
function Person(name,age){ this.name=name; this.age=age; } Person.prototype.sayName=function(){ console.log(this.name); } var person1=new Person(‘Sakura‘,22); person1.sayName();
很明显的一个问题就是,这段代码创建的对象似乎没有我们想象中那么完美,Person.prototype写在了构造函数外面,这样看起来很别扭,我们说封装,这咋没封到一块,咋还分道扬镳了?
那么我就想应该写成这样才对吧
function Person(name,age){ this.name=name; this.age=age; Person.prototype.sayName=function(){ console.log(this.name); } } var person1=new Person(‘Sakura‘,22); person1.sayName();
是不是很完美,perfect对不对?
但是我们再来做一个实验
function Person(name,age){ this.name=name; this.age=age; console.log(‘原型创建开始‘); Person.prototype.sayName=function(){ console.log(this.name); } console.log(‘原型创建结束‘); } var person1=new Person(‘Sakura‘,22); var person2=new Person(‘Misaka‘,20);
这段代码的意思是,每次实例化对象初始化原型对象之前都会在控制台输出一句话,创建完毕也会输出一句话,那么运行结果呢?
很明显这有问题啊,实例化了两个对象,然后这个原型被初始化了两次,这不是浪费吗,我们是不是应该在初始化原型对象前先确认一下原型中是否存在某个方法,如果存在就不再初始化,如果不存在然后再初始化原型?
所以这才是为师的完全体
function Person(name,age){ this.name=name; this.age=age; if(typeof this.sayName !=‘function‘){ console.log(‘原型创建开始‘); Person.prototype.sayName=function(){ console.log(this.name); } console.log(‘原型创建结束‘); } } var person1=new Person(‘Sakura‘,22); var person2=new Person(‘Misaka‘,20); //原型创建开始 //原型创建结束
妥妥的,这种方法只需要if判断一次即可,也避免了原型重复初始化的问题,这叫做动态原型模式
不过有一点需要注意的是,使用动态原型模式时,不能使用对象字面量重写原型,因为在已经创建了实例的情况下,重写原型就会切断现有实例与新原型之间的联系
so,方法有很多种,选择适合自己的才好
我用五篇博文阐述了封装对象的几种常见方法(没看过的小伙伴可以往前翻一翻),本人也只是自学了几个月的初学者,如果文中有什么写的不对的地方欢迎留言指出,我会及时改正
我刻意的省去了一些专业术语(比如封装以及面向对象等),是为了避免初学者觉得过于晦涩难懂,也是为了让初学者看完觉得“哦,原来这就是面向对象的封装啊”,不至于被一些术语砸的晕头转向
文中的例子以及部分概念引用自《JavaScript高级程序设计》
另外封装对象还有两种较为少见的方法,将在后续博文中补全
时间: 2024-12-06 05:01:26