JS类与面向对象
ES6 发布于 2015 年 6 月份,新增了类,模块,箭头函数等,而且新增了 13 个内置对象:Symble,Map,Set,WeakMap,WeakSet,ArrayBuffer,TypedArray,DataView,GeneratorFunction,Generator,Promise,Reflect,Proxy。
ES2015 中最大的改变应该就是启用 class 关键字,即类的概念。ES 本身是基于对象的语言,虽然启用了类的概念,但是依然不是基于类的语言而是基于对象的语言。
class 的用法
ES6 中使用 class 的操作除了定义正常的属性、方法外,最重要的就是 extends、super 以及 constructor 关键字的使用。
代码示例:
// 定义一个人的类
class Person {
constructor(sex) {
this.sex = sex;
}
printSex() {
console.log(`sex is ${this.sex}`);
}
}
// 定义一个学生类
class Student extends Person {
constructor(sex, age) {
super(sex);
this.age = age;
}
printStudentInfo() {
console.log(`student sex is ${this.sex}, age is ${this.age}`);
}
}
// 实例化
var stu = new Student(18, "male");
stu.printSex(); // sex is 18
stu.printStudentInfo(); // student sex is 18, age is male
ES 中的构造函数是利用 constructor 来定义的,而不像 C#和 java,使用与类名同名的函数来定义。
这里的 constructor 只能存在一个,由此也可以看出,JS 是基于对象的编程语言,而不是面向对象的编程语言。因为面向对象的编程语言具有三大特征:封装、继承、多态。JS 这里少个多态。
继承
上面的示例中,class Student extends Person,就是实现 Student 继承 Person,所以 Student 的实例 stu 可以使用 Person 的方法 printSex。
注意
在 JS 中,继承的方式有很多种,有时面试会考。多知道一些,更有助于理解 JS 语言的本身与发展,毕竟这里的 extends 只是 es6 提供的一个语法糖,class 的底层依然是构造函数。
模块
模块并不是对象,模块的使用分为两部分:定义模块和使用模块。它们一般位于不同的文件中,使用模块的文件可以调用定义模块的文件中导出的内容,有点像我们平时在一个页面中导入其他的 js 文件,但模块调用要比导入 js 文件更加强大。
模块的基本用法
模块最基础的用法就是导出和导入,分别使用 export 和 import 关键字来操作。只有模块中导出的变量(可以是变量,函数,类等)才可以被其他文件导入。
下面使用一个 React 示例,展示下基本用法,以及导入后重命名,默认导出,打包导出。
原因:如果通过本地加载 Html 文件 (比如一个 file:// 路径的文件), 你将会遇到 CORS 错误,因为 Javascript 模块安全性需要。你需要通过一个服务器来测试。
html 加载方式:<script type="module" src="module.mjs"></script>
导出模块: export.js
export const name = 'zzh'; // method 1, 基本导出方式
const getAge = () => 18;
const getSex = () => 'male';
export { getAge, getSex} // method 2, 打包导出方式
导入模块;import.jsx, 里面包含一个默认导出 TestModule
import React from 'react'
import { name, getAge as getAgeTest, getSex } from './export';
// getAge as getAgeTest: 利用as重命名
function TestModule () {
return (<div> name is {name}, age is {getAgeTest()}, sex is {getSex()} </div>);
}
export default TestModule;
调用 export 方式:
import React from 'react';
import Test from './import' // 可自定义名
ReactDOM.render(
<Test />,
document.getElementById('root')
);
调试结果:
name is zzh, age is 18, sex is male
一个小示例,包含了基本用法,以及导入后重命名,默认导出,打包导出,还有一种导入方式就是导入命名空间,用星号(*)将模块中导出的所有变量全部导入,这时需要一个命名空间,调用时使用命名空间调用就好了,例如将上面的导入改写:
import.jsx
import React from 'react'
import * as exportModule from './export';
function TestModule () {
return (<div> name is {exportModule.name}, age is {exportModule.getAge()}, sex is {exportModule.getSex()} </div>);
}
export default TestModule;