创建对象(10种)

112 阅读3分钟
1.new Object()

缺点:步骤多

2.字面量{}
var obj = {}

缺点:如果反复创建多个对象,代码冗余

3.工厂函数方式

反复生产,一个一个一个,叫工厂模式

function createPerson(name, age) {
    var o = new Object();
    o.name = name;
    o.age = age;
    o.say = function() {
        return o;
    }
}
var lilei = createPerson("lilei", 12);

缺点:将来没有办法判断类型,因为返回的对象,都是new Object

4.构造函数
function Person(name, age) {
    this.name = name;
    this.age = age;
    this.intr = function() {} // 这个方法的缺点是浪费内存
}
var lilei = new Person("lilei", 12);

构造函数有一个特点:

  • 构造函数内部,如果return一个引用类型的对象,则整个构造函数失效。而是返回这个引用类型的对象而已
  • 如果返回的是this,new构造的时候,返回的是新对象。如果只是执行函数,要看作用域,正常可能是window
  • 如果返回的是普通数据类型(string、number等)则正常构造
5.原型对象方式

所有属性和方法都通过原型对象(prototype)来实现。

但是js中要求:禁止修改共有属性。而是处理自己的自由属性

function Person() {} // 构造函数,什么都不干,因为我要把所有的属性和方法都放到原型对象上面
Person.prototype.name = "主人太懒";
Person.prototype.age = 0;
Person.prototype.intr = function() { console.info(this.name); }
var p1 = new Person();
p1.name = "lilei"; // 不能改原型,但是可以给自己添加自由属性(这里是name),可以看下图
var p2 = new Person();
p2.name = "han meimei"
console.info(p1);
console.info(p2);

原型对象.jpg

缺点:太繁琐了

6.混合模式(推荐)

也就是方法4和方法5的结合

// 构造函数
function Person(name, age) {
    this.name = name;
    this.age = age;
}
// 原型对象
Person.prototype.intr = function() {
    console.info(this.name);
}
var lilei = new Person("lilei", 12);

缺点:不符合封装。因为构造函数和给函数原型对象添加方法,是分开做的

7.动态混合模式

先创建完全相同的对象,再给子对象添加个性化属性

function Person(name,age){
    this.name = name;
    this.age = age;
    if (Person.prototype.intr === undefined) {
        Person.prototype.intr = function() {
            console.info(this.name)
        }
    }
}
var p1 = new Person("lilei", 12);
var p2 = new Person("hanmeimei", 12);

缺点:语义不符,只在if创建第一次对象时有意义

8.寄生构造函数
function Person(name,age){
    this.name = name;
    this.age = age;
    if (Person.prototype.intr === undefined) {
        Person.prototype.intr = function() {
            console.info(this.name)
        }
    }
}
// 开始了
function Student(name, age, className) {
    var p = new Person(name, age);
    p.className = className;
    return p
}
var p1 = new Student("lilei", 12, "二(8)");
var p2 = Student("hanmeimei", 15, "2") // 也可以不用new,因为Student中没有this
9.class
  • 如何定义class? 基于混合模式(方法6)基础上实现
function Person(name, age) {
    this.name = name;
    this.age = age;
}
// 原型对象
Person.prototype.intr = function() {
    console.info(this.name);
}

然后3步实现class

  • 1.用class{}包裹原构造函数 + 原型对象方法
class {
    function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    // 原型对象
    Person.prototype.intr = function() {
        console.info(this.name);
    }
}
  • 2.把构造函数名提升为class的名字,所有构造函数统一更名为constructor
class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    // 原型对象
    Person.prototype.intr = function() {
        console.info(this.name);
    }
}
  • 3.所有的原型方法(prototype),不再使用prototype前缀,也不用=function,直接简写为:方法名(){}
class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    intr() {
        console.info(this.name);
    }
}

只是新瓶装旧酒,换汤不换药

10.稳妥构造函数

利用闭包,不用this,不用new。安全,可靠

function Person(name, age) {
    var p = new Object();
    p.setName = function(value) { name = value }
    p.getName = function() { return name }
    p.getAge = function() { return name }
    return p;
}
var lilei = new Person("lilei", 12);
lilei.getName();

好处:只能通过我提供的api修改值