总结一下创建对象的几种方案:
- let Person={};
- let Person={
- name:"Jason",
- age:21
- }
开发的过程中最常见的方式,简单方便,内聚性强。
- var Person =new Object();
- Person.name = 'Jason'
- Person.age = 21
- function createPerson(name, age, height, address) {
- var p = {}
- p.name = name
- p.age = age
- p.height = height;
- p.address = address
- p.eating = function() {
- console.log(this.name + "在吃东西~")
- }
- p.running = function() {
- console.log(this.name + "在跑步~")
- }
- return p
- }
-
- var p1 = createPerson("张三", 18, 1.88, "广州市")
- var p2 = createPerson("李四", 20, 1.98, "上海市")
- var p3 = createPerson("王五", 30, 1.78, "北京市")
-
- // 工厂模式的缺点(获取不到对象最真实的类型)
- console.log(typeof p1) //object
在使用工厂模式创建对象的时候,可以将创建对象的逻辑封装在一个函数里面,避免了重复代码,但是通过工厂函数创建的对象都是object类型,如果希望创建出来的对象有一个共同的类型,于是就出现了第四种创建对象的模式
- // 规范: 构造函数的首字母一般是大写
- function Person(name, age, height, address) {
- this.name = name
- this.age = age
- this.height = height
- this.address = address
-
- this.eating = function() {
- console.log(this.name + "在吃东西~")
- }
-
- this.running = function() {
- console.log(this.name + "在跑步")
- }
- }
- var p1 = new Person("张三", 18, 1.88, "广州市")
- var p2 = new Person("李四", 20, 1.98, "北京市")
- console.log(p1 instanceof Person) //true
- console.log(p2 instanceof Person) //true
- console.log(p1 instanceof Object) //true
- console.log(p2 instanceof Object) //true
通过构造函数可以确保创建出来的对象都具有相同的类型
但是这种方式也存在缺陷:
每个对象里面都有公用的函数,意味着每次创建一个对象都会创建一个函数实例,因此可以这个函数放到外面,但是会污染全局作用域。
就是每个方法都要在每个实例上重新创建一遍,方法指的就是我们在对象里面定义的函数。如果方法的数量很多,就会占用很多不必要的内存。于是出现了第五种创建对象的方法
- function Person(){}
- Person.prototype.name = 'Nike';
- Person.prototype.age = 20;
- Person.prototype.firends= [];
- Person.prototype.sayName = function(){ alert(this.name);};
- let person1 = new Person()
- person1.name = '哈哈' //往person1上面新增了name属性
- person1.friends.push('kobe') //会修改原型上的值,所有的实例都会受到影响
- let person2 = new Person()
- console.log(person2.friends) // ['kobe']
这种方式将对象的属性和方法都保存到函数的原型上,创建出来的所有实例都可以访问到原型上的属性和方法,而不用在每个对象上都保存一份函数实例。
缺点:
1.这些属性并没有保存到对象自身上,而是通过原型链去访问
2.如果修改了name属性,相当于在person1上面新增了属性name
3.如果修改了一个引用数据类型,则会修改原型上面的值,所有的实例都会收到影响
- function Person(name, age, height, address) {
- this.name = name
- this.age = age
- this.height = height
- this.address = address
- }
-
- Person.prototype.eating = function() {
- console.log(this.name + "在吃东西~")
- }
-
- Person.prototype.running = function() {
- console.log(this.name + "在跑步~")
- }
-
- var p1 = new Person("why", 18, 1.88, "北京市")
- var p2 = new Person("kobe", 20, 1.98, "洛杉矶市")
-
- p1.eating()
- p2.eating()
-
实例属性都是在构造函数中定义的,而所有实例方法则是在原型中定义。
这种模式是ECMAScript中使用最广泛,认可度最高的一种创建自定义类型的方法,可以说这是用来定义引用类型的一种默认模式。