JavaScript创建对象的方式

2022-11-16  本文已影响0人  狂奔的胖蜗牛

1.使用工厂模式创建

使用特定的函数创建对象。

function createClass(name, age) {
    let o = new Object();
    o.name = name;
    o.age = age;
    o.say = function() {
        console.log(this.name, this.age)
    }
    return o;
}

let c = createClass('xxx', 11);
c.say();

函数createClass接收两个参数,然后函数的内部通过这两个参数创建出一个对象返回。
这种创建方式,有个问题,就是不知道内部创建的对象是什么类型的。

2.构造函数创建

使用构造函数模式,可以这样创建对象。

function CustomClass(name, age) {
    this.name = name;
    this.age = age;
    this.say = function() {
        console.log(this.name, this.age);
    }
}
let c = new CustomClass('xxx', 11);
c.say();

通过CustomClass()构造函数代替了createClass()工厂函数。实际上内部是一致的,区别在于:


new关键字的作用:


通过这种方式创建的对象,会有一个属性constructor指向了CustomClass,如下所示:

console.log(c.constructor);
console.log(c.constructor === CustomClass);
输出:
ƒ CustomClass(name, age) {
    this.name = name;
    this.age = age;
    this.say = function() {
        console.log(this.name, this.age);
    }
}
true

这样,我们就可以通过constructor知道对象的类型。不过一般来说,都是通过instanceof操作符来判断对象的类型的。如下:

console.log(c instanceof CustomClass)
console.log(c instanceof Object)
输出:
true
true

可以看到,都是true,之所以Object也是true,那是因为所有的对象都继承自Object。

构造函数可以赋值给变量,然后通过变量来创建对象。

const CustomClass = function(name, age) {
    this.name = name;
    this.age = age;
    this.say = function() {
        console.log(this.name, this.age);
    }
}
let c = new CustomClass('xxx', 11);
c.say();

调用构造函数的时候,参数可以不写,只要有new操作符,就可以调用构造函数创建对象。

let c = new CustomClass();

构造函数和普通函数没有区别,唯一的不同就是调用时候的不同。构造函数前面如果添加了new操作符,那么他就会创建出一个对象,否则,他就是一个普通的函数。


通过构造函数创建的对象,会有一个问题,就是对象的方法每次创建对象时,都是新建一个方法,然后赋值给对象。这样就会导致不同的对象,相同的方法不是同一个对象。如下所示:

let c1 = new CustomClass();
let c2 = new CustomClass();
console.log(c1.say === c2.say)
输出:
false

这是可以解决的,我们只需要让函数只创建一次就可以了,如下所示:

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

function say() {
    console.log(this.name, this.age);
}

在外部创建,然后内部引用同一个函数,可以解决上述问题。但是这样非常容易造成需要在外部定义多个函数,导致代码可能会被分散在各个地方。

3.原型模式创建

每一个函数,都有一个prototype属性,我们叫做原型。我们可以通过prototype属性,将需要在构造函数内赋值的值,在外部赋值给prototype属性,这样,创建出来的对象实例就都会通过原型获得这些值。

function Person() {}
Person.prototype.name = "哈哈哈";
Person.prototype.age = 29;
Person.prototype.sayName = function() {
    console.log(this.name);
};
let person1 = new Person();
person1.sayName(); // "哈哈哈"
let person2 = new Person();
person2.sayName(); // "哈哈哈"
console.log(person1.sayName == person2.sayName); // true

我们需要了解到,无论何时,只要创建出一个函数,就会给该函数创建出一个prototype属性,指向了原型对象。默认情况下,所有的原型对象会自动获得一个constructor属性,指向与之关联的构造函数。
然后在调用属性或者方法的时候,会先在对象实例本身进行搜索,如果实例上有该方法属性,则执行,没有则会沿着prototype找到原型对象,如果原型对象上有,则执行。


in操作符可以判断属性是否可用。该属性在实例或者原型上,都会返回true。
hasOwnProperty方法,如果属性在原型上,则会返回true。

4.通过类创建

使用关键字class声明类,然后创建出对象。

// 类声明
class Person {}
// 类表达式
const Animal = class {}

可使用constructor关键字,在类定义内部创建类的构造函数,constructor会告诉解释器,在使用new操作符创建新实例时,调用该函数。如下:

class Person {
    constructor() {
        console.log('init')
    }
}
let p = new Person() // init

可在实例创建时,传入参数,也可以不传,不传参数时,创建的时候类后面的()也可以省略。如下:

class Person {
    constructor(name) {
        this.name = name
        console.log('init', name)
    }
}
let p = new Person() // init undefined
let p2 = new Person("aa") // init aa
let p3 = new Person // init undefined

类构造和构造函数构造主要区别是,类构造必须使用new操作符,构造函数的话,不写new操作符,那就是一个普通的函数,类构造不写则会报错。

上一篇 下一篇

猜你喜欢

热点阅读