前端入门(二)面向对象与闭包

280 阅读3分钟

二、面向对象与闭包

2.1 面向对象

2.1.1 类

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

    introduce() {
        console.log(`我的名字是${this.name},今年${this.age}岁`)
    }
}

class Student extends Person {
    constructor(name, age, grade, mhobby) {
        super(name, age);
        this.grade = grade;
        this.mhobby = mhobby;
    }

    introduce() {
        super.introduce();
        console.log(`读${this.grade}年级,爱好${this.mhobby}`)
    }

    set hobby(value) {
        this.mhobby = value;
    }

    get hobby() {
        return this.mhobby;
    }
}

let someone = new Student("小明", 12, 5);
someone.hobby = '打球'
someone.introduce();

/*-----输出-----*/
//我的名字是小明,今年12岁
//读5年级,爱好打球

2.1.2 属性表达式

let methodName = 'getArea';
class Square {
  constructor(length) {
    // ...
  }

  [methodName]() {
    // ...
  }
}

上面代码中,Square类的方法名getArea,是从表达式得到的。

2.1.3 class 表达式

采用 Class 表达式,可以写出立即执行的 Class

let person = new class {
  constructor(name) {
    this.name = name;
  }

  sayName() {
    console.log(this.name);
  }
}('张三');

person.sayName(); // "张三"

2.1.4 静态方法

class Foo {
  static classMethod() {
    return 'hello';
  }
}

Foo.classMethod() // 'hello'

var foo = new Foo();
foo.classMethod()
// TypeError: foo.classMethod is not a function

注意:

  1. 如果静态方法包含this关键字,这个this指的是类,而不是实例
  2. 静态方法可以与非静态方法重名
  3. 父类的静态方法,可以被子类继承

2.1.5 静态属性

// 老写法
class Foo {
  // ...
}
Foo.prop = 1;

// 新写法
class Foo {
  static prop = 1;
}

2.1.6 实例属性的新写法

class foo {
  bar = 'hello';
  baz = 'world';

  constructor() {
    // ...
  }
}

一眼就能看出,foo类有两个实例属性,一目了然。另外,写起来也比较简洁。

2.2 闭包

  • 对于底层来说,闭包是一个栈,闭包可以使函数执行完这个栈也不回收。

  • 对于高层来说,闭包是函数当作对象处理

2.3 ES6 模块化

浏览器还不支持,但是可以用 webpack

npm i webpack -g 
#-g 全局安装
//webpack.config.js
const path = require('path') //node 导入模块方式
module.exports={
    //production 生产模式、development 开发模式
    mode:'production'
    //同级目录必须加 ./	import同级目录也要加 ./
    entry:'./index.js'
    output:{
    //__dirname 当前脚本的工作目录
    	path:path.resolve(__dirname,'build'),
    	filename:'bundle.js'
	}
}

2.3.1 export

  • 可输出变量、函数、类
// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;

export { firstName, lastName, year };
  • as 关键字

as 用来重命名对外的接口,并且重命名后可以输出两次

function v1() { ... }
function v2() { ... }

export {
  v1 as streamV1,
  v2 as streamV2,
  v2 as streamLatestVersion
};
  • 动态更新
export var foo = 'bar';
setTimeout(() => foo = 'baz', 500);

2.3.2 import

as关键字,动态更新同样适用。动态更新较难排查问题,因此 import 的变量尽量只作只读处理,不要轻易更改它的值

// main.js
import { firstName, lastName, year as time } from './profile.js';
//as 关键字同样适用

function setName(element) {
  element.textContent = firstName + ' ' + lastName;
}

2.3.3 模块的整体加载

即用星号(*)指定一个对象,所有输出值都加载在这个对象上面

import * as profile from './profile.js';

2.3.4 export default 命令

本质上,export default就是输出一个叫做default的变量或方法,然后系统允许你为它取任意名字

// export-default.js
export default function () {
  console.log('foo');
}


// import-default.js
import customName from './export-default';
customName(); // 'foo'

2.3.5 模块的继承

假设有一个circleplus模块,继承了circle模块

// circleplus.js
export * from 'circle';
export var e = 2.71828182846;
export default function(x) {
  return Math.exp(x);
}
//注意,export *命令会忽略 circle 模块的default方法


// main.js
import * as math from 'circleplus';
import exp from 'circleplus';
console.log(exp(math.e));

2.3.6 跨模块常量

// constants.js 模块
export const A = 1;
export const B = 3;
export const C = 4;


// test1.js 模块
import * as constants from './constants';
console.log(constants.A); // 1
console.log(constants.B); // 3


// test2.js 模块
import {A, B} from './constants';
console.log(A); // 1
console.log(B); // 3

2.3.7 import()

// 报错
if (x === 2) {
  import MyModual from './myModual';
    //不支持动态加载
}

import()函数,支持动态加载模块

//import()返回一个 Promise 对象
const main = document.querySelector('main');

import(`./section-modules/${someVariable}.js`)
  .then(module => {
    module.loadPageInto(main);
  })
  .catch(err => {
    main.textContent = err.message;
  });
  • import()函数可以用在任何地方,不仅仅是模块,非模块的脚本也可以使用。它是运行时执行,也就是说,什么时候运行到这一句,就会加载指定的模块。
  • import()函数与所加载的模块没有静态连接关系,这点也是与import语句不相同。
  • import()类似于 Node 的require方法,区别主要是前者是异步加载,后者是同步加载