一、类
1、认识类(class)
类是对象的一个抽象,是对象的一个模板。对象是类的实例化。
定义:
class 类名 {
contructor(paramsList){ // 创建构造器
this.x = x
...
}
// handle
}
注意:
(1)类名一般首字母大写,用来跟普通函数进行区别。
(2)类不能直接调用,必须进行实例化处理。
(3)类的类型是function。
(4)类本身就指向构造函数。
(5)类不存在变量位置提升。
let p1 = new Person() // 会报错!实例化对象的代码必须写在类定义之后
class Person(){}
(6)类中的this指向的是当前实例化的对象的。
实例化:类在ES5中就是一个构造函数,可以通过new关键字进行实例化。var 实例化对象 = new 类名(实参列表);
class Person {
constructor(name, sex, age, addr) {
this.id = Math.ceil(Math.random() * 1000).toString();
this.name = name;
this.sex = sex;
this.age = age;
this.addr = addr
}
info() {
return this.name + ":" + this.addr
}
}
let p1 = new Person('zs', '男', 25, 'china')
let p2 = new Person('ls', '女', 22, 'china')
console.log(p1.name);
console.log(p1.info());
console.log(p2.info());
console.log(typeof Person);//function
console.log(Person === Person.prototype.constructor);//true
2、constructor():构造器
当实例化一个类时,它默认执行这个方法(也即是不需要单独去调用它)。
每个类有且只能有一个constructor方法,如果没有定义,类会自动添加一个constructor,内容为空。
作用:用来初始化数据,或将传进来的数据挂到实例化对象上。
class Animal1 {
eat() {
console.log("eat()");
}
}
let cow1 = new Animal1()
console.log(cow1);
class Animal2 {
constructor(name, type) {
this.name = name;
this.type = type
var otherName = name;// 这里初始化变量,在外面获取不到,只能在当前范围内使用
}
eat() {
console.log(this.name + this.type);
}
}
let cow2=new Animal2('奶牛','草')
console.log(cow2);
console.log(cow2.otherName);//undefined
3、class表达式
const Person = class Human{};
const Person = class {};
const person = new class {}();
const Person1=class Human{}
const Person2=class{}
const person=new class{}()
console.log(Person1,Person2,person);
console.log(new Person1());
console.log(new Person2());
console.log(person);
4、class中的getter(取值)和setter(存储值)函数
getter与setter成对出现。
注意:当在类中出现getter和setter时,这时这个属性的值就取不到了,会自动产生一个以_开头的属性
class Human{
constructor(name,tel){
this.name=name;
this.tel=tel;
}
//getter取值
get tel(){
return this._tel
}
//setter存值
set tel(tel){
this._tel=tel
}
}
let h1=new Human("zs",'11111111111')
// h1._tel='11111111111'// 会自动调用setter
h1.tel='11111111111'
console.log(h1.tel);// 会自动调用getter
5、class中的generator方法
generator是ES6新增的用来解决异步编程的方法,语法与传统函数不一样。generator就是一个状态机,封装了多个内部状态。执行generator函数会返回一个遍历器对象。
generator有两个特征:
(1)function关键字与函数名之间有一个*号;
(2)函数体内部使用yield(产出)表达式定义多个内部状态(用来提取遍历后的数据)
注意:凡是方法名前加*,就表明这是一个generator函数,就可以使用状态机yield。
class Person {
constructor(...args) {// 这里的...将把传过来的参数解析成一个数组
this.args = args
}
//如果方法名前加*,表明这是一个generator函数
//Symbol.iterator是一个内置的Symbol方法,它的作用是用来设置遍历器
*[Symbol.iterator](){
for(let stu of this.args){
yield stu
}
}
}
for(let v of new Person('zs','ls','ww')){
console.log(v);
}
6、class中的静态方法
在ES6中静态属性声明还未列入规范,也就意味在ES6中不能用static去定义静态属性。(结论:在ES6中只有静态方法,没有静态属性)静态方法可以使用static定义。静态方法只能写在class中,constructor之外,也可通过类添加。
静态方法特征:
(1)它不属于实例化对象,不能通过实例化对象调用,它只属于类自身。
(2)它只能通过类调用,格式:类名.静态方法名(参数)。
(3)它可以跟类中的其它方法同名。
class Student {
constructor() {
}
static study() {
console.log("study");
}
}
let s1 = new Student()
Student.study()
Student.sports = () => {
console.log('sport');
}
Student.sports()
7、类的继承
类的继承就是让子类拥有父类所有属性和方法,实现资源共享。
class 子类名 extends 父类名 {
constructor(fatherArgs, childArgs){
super(fatherArgs);// super用于继承父类的属性
...
}
}
// 父类
class Animal {
constructor(props) {
this.name = props.name || 'Unknown';
}
eat() { // 父类共有的方法
console.log(this.name + '喜欢吃东西。');
}
}
// 子类(同时继承父类Animal)
class Bird extends Animal { // 子类可以继承父类所有属性的方法,同时也可以拥有自己的属性和方法
constructor(props, myAttribute) { // props是继承过来的属性,而myAttribute是该子类自己的属性
super(props); // 相当于获得父类的this指向(相当于ES5中的Animal.call(this)
this.type = props.type || 'Unknown';
this.attr = myAttribute;
}
fly() { // 子类私有的方法
console.log(this.name + '能飞得很远!');
}
myAttr() { // 子类私有的方法
console.log(this.type + '---' + this.attr);
}
}
// 实例化
let myBird = new Bird({
name: '小燕子',
type: '卵生动物'
}, '鸟类');
myBird.eat();
myBird.fly();
myBird.myAttr();
8、Object.getPrototypeOf()
通常可以使用instanceof来判断一个对象是否属于某一个类的实例对象。
通过Object.getPrototypeOf()可以获得一个类的隐式原型,用来判断一个类是否继承了另一个类。
//instanceof 判断某个对象是否是某个类的实例
class Human {
constructor() {
}
say() {
console.log('hello');
}
}
let man = new Human()
let obj = {}
console.log(obj instanceof Human);// false 说明obj不是Human的实例
console.log(man instanceof Human);// true
console.log(obj instanceof Object, man instanceof Object);// true true 说明所有的对象都是Object的实例
// Object.getPrototypeOf() 一个类是否继承了另一个类
class Person {
constructor() {
}
}
class Teacher extends Person {
constructor() {
super()
}
}
class Student {
constructor() {
}
}
console.log(Object.getPrototypeOf(Teacher) === Person);// true 说明Teacher这个类继承了Person这个父类
console.log(Object.getPrototypeOf(Student) === Person); // false
9、super
super用于继承父类的属性和方法。
class Person{
constructor(info){
this.sno=info.sno;
this.name=info.name
}
study(){
return this.name+" study"
}
}
class Student extends Person{
constructor(info){
super(info)//继承父类的所有属性
}
content(){
console.log(super.study()+'web'); // 这里的super用来继承(调用)父类的方法
console.log(this.study()+'web');
}
}
let tom=new Student({son:'111111',name:'zs'})
tom.content()
二、模块化开发
模块化程序设计是指在进行程序设计时将一个大程序按照功能划分为若干小程序模块,每个小程序模块完成一个确定的功能,并在这些模块之间建立必要的联系,通过模块的互相协作完成整个功能的程序设计方法。模块,就是指一个独立功能的JS文件。
ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。
在ES5(在ES6中仍然沿用)可以使用的模块化规范有:
CommonJS - 用在后台(是后台的一套模块化规范,目前它的实行者是Node.js)。
AMD - 用在前端,规范是通过RequireJS实现的。
CMD - 用在前端,规范是通过SeaJS实现的。
注意:在进行大型项目开发时,必用到模块化开发。
import{PI,r,Area,str,obj} from './modules01'
console.log(r);
console.log(Area());
console.log(str);// undefined 因为模块中没有暴露str
console.log(obj.gNum*obj.gPrice);
export const PI = 3.14
export let r = 10
let str = "abc"
export var obj = {
gName:"签字笔",
gPrice: 23,
gNum: 2999
};
export function Area() {
return PI * Math.pow(r, 2)
}
1、模块化开发基本用法
(1)用export导出(暴露变量或方法)
// // 用法1:
// export var a = 10;
// export function result() {
// return a * a;
// }
// // 用法2:
// var a = 11;
// function result() {
// return a * a;
// }
// export {a, result}
// // 用法3:
// var variantA = 12;
// function result() {
// return variantA * variantA;
// }
// export {variantA as a, result as rs}
// // 用法4:
// export default {
// a: 122,
// rs: function(num){
// return num * num;
// }
// }
// 用法5(推荐写法):
let a = 13;
let rs = function () {
return a * a;
};
export default { // 一个模块export default只能出现一次
a, rs
}
(2)用import导入
// 用法1(导入整个文件(模块))
import './modules02'
// 用法2(选择性地导入)
import { a } from './modules02'
// 用法3(导入通过export default导出的模块)
import api from './modules02'
// 用法4(模块的整体加载)
import * as api from "./modules02"
// 用法1:
// export var a = 10;
// export function result() {
// return a * a;
// }
// 用法2:
// var a = 11;
// function result() {
// return a * a;
// }
// export {a, result}
// 用法3:
// var variantA = 12;
// function result() {
// return variantA * variantA;
// }
// export {variantA as a, result as rs}
// 用法4:
// export default {
// a: 122,
// rs: function(num){
// return num * num;
// }
// }
// 用法5(推荐写法):
let a = 13;
let rs = function () {
return a * a;
};
export default { // 一个模块export default只能出现一次
a, rs
}
2、export命令的用法
用法1:
export var a = 10;
export function result() {
return a * a;
}
用法2:
var a = 11;
function result() {
return a * a;
}
export {a, result}
用法3:
var variantA = 12;
function result() {
return variantA * variantA;
}
export {variantA as a, result as rs}
用法4:
export default {
a: 122,
rs: function(num){
return num * num;
}
}
用法5(推荐写法):
let a = 13;
let rs = function(){
return a * a;
};
export default { // 一个模块export default只能出现一次
a, rs
}
2-3 import命令用法
// 用法1(导入整个文件(模块))
import './modules02'
// 用法2(选择性地导入)
import { a } from './modules02'
// 用法3(导入通过export default导出的模块)
import api from './modules02'
// 用法4(模块的整体加载)
import * as api from "./modules02"
三、严格模式
ES6 的模块自动采用严格模式,不管你有没有在模块头部加上"use strict";。
严格模式主要有以下限制:
变量必须声明后再使用
函数的参数不能有同名属性,否则报错
不能使用with语句
不能对只读属性赋值,否则报错
不能使用前缀 0 表示八进制数,否则报错
不能删除不可删除的属性,否则报错
不能删除变量delete prop,会报错,只能删除属性delete global[prop]
eval不会在它的外层作用域引入变量
eval和arguments不能被重新赋值
arguments不会自动反映函数参数的变化
不能使用arguments.callee
不能使用arguments.caller
禁止this指向全局对象
不能使用fn.caller和fn.arguments获取函数调用的堆栈
增加了保留字(比如protected、static和interface)