JavaScript - 面向对象编程(OOP)
概述
在JavaScript里面,有多种创建对象的方式:
- 直接创建(object literal),创建出来的对象的原型对象是Object;
- 使用factory function来创建对象,创建出来的对象的原型对象可能是Object,也可能不是Object(视情况而定);
- 使用constructor function来创建对象,创建出来的对象的原型对象是constructor_function_name.prototype;
- 使用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 property
(raiseSalary
是harry
这个对象的一个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。输出的结果如下图:
那么如何让所有的
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
输出的结果如下图:
可以看到说,这里已经形成了原型链(
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来创建对象。但是,两种方式,创建的对象有差别:
- factory function,用new创建的对象,如果没有使用到
Object.setPrototypeOf()
,其原型对象是Object; - constructor function,用new创建的对象,其原型对象是(constructor_function_name.prototype)。比如上面
console.log(newEmployee.__proto__ === Employee.prototype)
的输出结果是true
。
- factory function,用new创建的对象,如果没有使用到
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 functionEmployee
. Theconstructor
keyword declares the body of theEmployee
constructor function. TheraiseSalary
method is added toEmployee.prototype
.
转载自:https://juejin.cn/post/6951803345879171079