js 创建对象10种方法

194 阅读3分钟

1. 创建空对象 new Object()

var obj = new Object() 

缺点: 每个属性方法都要重新单独设置。

2. 字面量{}

var obj = {}

缺点: 多个一个的对象不能复用

3. 工厂函数方式

缺点: 本质还是new Object(),无法根据对象的原型对象准确判断对象的类型

function createUser(name, age) {
    var o = new Object();
    o.name = name;
    o.age = age;
    o.say = function () {
        alert(this.name);
    }
    return o;
}
var p1 = createUser("jason ",18); 

4. 构造函数方式

  • 先用构造函数定义一类对象的统一属性结构和方法,
  • 再用new调用构造函数反复创建相同属性结构, 不同属性值的多个对象

缺点: 如果构造函数中包含方法, 则重复创建, 浪费内存

function User(name, age) {
    this.name = name;
    this.age = age;
    this.info = function () {//这里每次new 都会重复创建 info 对象
    
    }
}
var user = new User("jason", 11)

5. 原型对象prototype

先创建空的对象, 再给对象的原型上添加个性的属性和方法。

缺点:

  • 所有父对象属性方法不能聚合在一起
  • 所有属性引用同一个,会互相干扰
function Person() {}
Person.prototype.name = "jason";
Person.prototype.age = 18;
Person.prototype.say = function () {
    console.log(this.name);
};
var p1 = new Person(); //创建一个实例p1
p1.name = "jason" //由于js 禁止修改原型上的属性,当失败时,会自动给子对象添加改属性。
var p2 = new Person(); //创建实例p2
p2.name = "jason2"; //同上
console.log(p1); 
console.log(p2);

6. 混合/组合模式 (构造函数+prototype)

目前比较多人使用的方法

先用构造函数创建对象, 再用原型添加定制的属性和方法。

优点:

  • 属性统一聚合
  • 方法共用一个

缺点:

  • 属性和方法被分离
function Person(name, age) {
    this.name = name;
    this.age = age;
}
Person.prototype.say = function () {//这里定义的原型方法say ,所有实例不会重复创建方法对象
       console.log(this.name); 
}
var p1 = new Person("jason", 11);
var p2 = new Person("jason2", 12); 
p1.say()
p2.say()

7. 动态混合 (构造函数+ prototype放在构造函数if判断)

只用一个构造函数创建,把原型的方法通过判断放入构造函数里。

缺点: 虽然已经把构造函数里的变量和方法合并在一起。但是整体可编写性和可读性差

function Person(name, age) {
    this.name = name;
    this.age = age;
    if (Person.prototype.say === "undefined") { //为了避免重复创建say对象方法,所以添加判断,使得智能执行一次。
        Person.prototype.say = function () {
            console.log(this.name);
        };
    }
}
var p1 = new Person("jason", 11);
var p2 = new Person("jason2", 12); 
console.log(p1);
 console.log(p2);

8. 寄生构造函数 (子构造函数里调父构造函数)

缺点: 可读性差,逻辑有点交叉混乱。

function Person(name, age) {
    this.name = name;
    this.age = age;
}

function Student(name, age, className) {
    var p = new Person(name, age); //
    p.className = className //这里可以新增属性
    return p;
}
var p1 = new Student("jason", 11, "初一");
var p2 = new Student("jason2", 12, "初二"); 
console.log(p1.className); 
console.log(p2.className);

9. ES6 class:

class User2 {
    constructor(name,age){
        this.name = name
        this.age = age
    }
    info(){
        console.log("name:",this.name)
        console.log("age:",this.age)
    }
}

var user2 = new User2("jason",18)
user2.info()

10. 闭包

优点

  • 不用this和new
  • 并且是一个独立的沙盒空间 缺点
  • 容易造成内存泄漏
  • 所有属性也要通过方法的方式定义,代码冗余
function Person(name, age) {
    var p = {};
    p.getName = function () {
        return name
    };
    p.setName = function (value) {
        name = value
    };
    p.getAge = function () {
        return age
    }
    return p;
}
var p1 = Student("jason", 11);
var p2 = Student("jason2", 12); 
console.log(p1.getName());
console.log(p1.getAge());
console.log(p2.getName());
console.log(p2.getAge());