likes
comments
collection
share

JavaScript - 面向对象编程(OOP)

作者站长头像
站长
· 阅读数 5

概述

在JavaScript里面,有多种创建对象的方式:

  1. 直接创建(object literal),创建出来的对象的原型对象是Object;
  2. 使用factory function来创建对象,创建出来的对象的原型对象可能是Object,也可能不是Object(视情况而定);
  3. 使用constructor function来创建对象,创建出来的对象的原型对象是constructor_function_name.prototype;
  4. 使用class syntax来创建对象,创建出来的对象的原型对象是class_name.prototype。 假设要创建一个对象,用上面不同的方式来创建,创建出来的对象,可能就会有一些区别(原型对象可能不一样)。

Object Literal

创建一个object:

let harry = {
    name: 'Harry Smith',
    salary: 90000,
    raiseSalary: function(percent) {
        this.salary *= 1 + percent/100; 
    }
};

上面,raiseSalary叫做function-valued propertyraiseSalaryharry这个对象的一个property)。 它的另一种写法是:

let harry = {
    name: 'Harry Smith',
    salary: 90000,
    raiseSalary(percent) {
        this.salary *= 1 + percent/10; 
    }
};

Factory Function

A factory function is simply a function that returns an object.

用factory function来创建object的时候,不需要使用new这个关键字。 下面就是一个factory function:

function createEmployee(name, salary) {
    return {
        name: name,
        salary: salary,
        raiseSalary: function (percent) {
            this.salary *= 1 + percent / 100;
        },
    };
}

const newEmployee = createEmployee("Harry Smith", 80000); 

用上面这个factory function来创建的每一个object里面,都有一个function-valued raiseSalary property。输出的结果如下图:

JavaScript - 面向对象编程(OOP) 那么如何让所有的employee对象共享同一个raiseSalary函数呢?JavaScript里面就是用Prototypes来实现。

Prototypes

下面这个prototype object里面就包含了共享的raiseSalary函数:

const employeePrototype = {
    raiseSalary: function(percent) {
        this.salary *= 1 + percent/100; 
    }
}

重新来写这个createEmployee函数:

function createEmployee(name, salary) {
    const result = {name, salary}; 
    Object.setPrototypeOf(result, employeePrototype); 
    return result; 
}

const newEmployee = createEmployee("Harry Smith", 80000); 
console.log(newEmployee.__proto__ === employeePrototype);  // true

输出的结果如下图:

JavaScript - 面向对象编程(OOP) 可以看到说,这里已经形成了原型链(prototype chain),新创建的newEmployee对象的原型对象是employeePrototype,而employeePrototype的原型对象是Object。

console.log(Object.getPrototypeOf(newEmployee)); 
// 输出结果是{raiseSalary: ƒ}

Constructor Function

上面我们看了factory function,下面我们来看constructor function:

function Employee(name, salary) {
    this.name = name;
    this.salary = salary;
}

Employee.prototype.raiseSalary = function(percent) {
    this.salary *= 1 + percent/100; 
}

const newEmployee = new Employee('Harry Smith', 90000); 
console.log(newEmployee.__proto__ === Object.prototype); // false
console.log(newEmployee.__proto__ === Employee.prototype); // true

针对constructor function,JavaScript里面用new来创建一个新的对象。

Factory Function vs Constructor Function

  • 两者都可以用来创建新的对象;
  • constructor function的函数名,首字母大写;
  • 前面我们提到,用factory function来创建对象的时候,不需要使用new这个关键字。但是,虽然不需要,其实是可以用new来创建的。也就是说,factory function和constructor function,都可以用new来创建对象。但是,两种方式,创建的对象有差别:
    1. factory function,用new创建的对象,如果没有使用到Object.setPrototypeOf(),其原型对象是Object;
    2. constructor function,用new创建的对象,其原型对象是(constructor_function_name.prototype)。比如上面console.log(newEmployee.__proto__ === Employee.prototype)的输出结果是true

Class Syntax

如今,JavaScript又有了跟Java类似的class syntax:

class Employee {
    constructor(name, salary) {
        this.name = name;
        this.salary = salary;
    }

    raiseSalary(percent) {
        this.salary *= 1 + percent / 100;
    }
}

这个class syntax跟constructor function所做的事是一样的。推荐使用class syntax。

Behind the scenes, the class declaration merely declares a constructor function Employee. The constructor keyword declares the body of the Employee constructor function. The raiseSalary method is added to Employee.prototype.

转载自:https://juejin.cn/post/6951803345879171079
评论
请登录