====================es6对象 新增的对象字面量语法========================== 1. 成员速写: 如果对象字面量初始化时,成员的名称来自于一个变量, 并且和变量的名称相同,则可以进行简写 es6以前使用返回对象,需要以下的写法: /** * @description: 创建要给用户, 返回一个对象 * @param : loginId 登录的id * @param : loginPwd 登录的密码 * @param : nickName 昵称 * @return: {*} 返回一个对象 */ function createUser(loginId, loginPwd, nickName) { return { loginId: loginId, loginPwd: loginPwd, nickName: nickName, id: Math.random() } } es6后,可以这么写: /** * @description: 创建要给用户, 返回一个对象 * @param : loginId 登录的id * @param : loginPwd 登录的密码 * @param : nickName 昵称 * @return: {*} 返回一个对象 */ function createUser(loginId, loginPwd, nickName) { return { loginId, loginPwd, nickName, id: Math.random() } } 2. 方法名速写: 在对象字面量初始化时, 方法可以省略冒号和function: es6以前: const user = { name:'twinkle', age: 100, sayHello: function(){ } } es6以后: const user = { name:'twinkle', age: 100, sayHello(){ } } 3. 计算属性名 有的时候,初始化对象时, 某些属性名可能来自于某个表达式,在计算中可以使用中括号来表示该属性名是通过计算得到的。 例如: const prop1 = "name"; const porp2 = "age"; // es6 以前创建一个带有变量的对象属性需要以下做法 const user = {}; user[prop1] = "twinkle"; user[porp2] = 100; // es6后可以这么写,初始化就可以赋值: const user1 = { [prop1]: "twinkle", [porp2]: 100 } ====================es6对象 新增的对象API========================== 以下方法都是静态方法,直接应用在Object上: 1. Object.is(obj1, obj2) 用来判断两个对象是否相等 用于解决一些历史遗留问题: 如: NaN === NaN // false \ +0 === -0 // false 用于判断两个数据是否相等,基本上是严格相等(===)是一致的,除了以下两点: 1. NaN 与 NaN 2. +0 与 -0 2. Object.assign() 用于对象的混合 如: const obj1 ={a: 123, b: 234} const obj2 = {c, 123, a:234} 这个方法与es7 的...是一样的 如{...obj1, ...obj2} 与 Object.assign(obj1, obj2) 相同 Object.assign(obj1, obj2) 这个方法会改动第一个参数,返回的是obj1,巧妙的写法 Object.assign({}, obj1, obj2) 3. Object.getOwnPropertyNames 的枚举顺序 Object.getOwnPropertyNames() 这个方法之前就存在, 只是没有明确的要求,如何排序由浏览器厂商来排序。 es6规定了该方法的数组的排序如下: 先排数字(升序),在排其他 4. Object.setPrototypeOf() 用于设置某个对象的隐士原型 比如: Object.setPrototypeOf(obj1, obj2) 相当于 obj1.__proto = obj2 ===================es6面向对象================ 面向对象: 是一种编程思想, 和具体的语言无关 对比面向过程: 面向过程: 思考的切入点是功能的步骤 面向对象: 思考的切入点是对象的划分 如: [大象装冰箱] 面向过程的思考如下: 1. 冰箱门打开 2. 大象装进去 3. 冰箱关上 面向对象的思考如下: 大象对象 冰箱对象 冰箱的方法: 打开 关闭 装东西 步骤: 1. new 一个冰箱 调用打开的方法 2. new 一个大象 冰箱装好大象 3. 冰箱的关闭 总结: 面向对象用于大型的项目,更好的维护;面向过程用于小型的项目,快速开发 类: 构造函数的语法糖 class 传统的构造函数的问题 function Animal(type, name, age, sex) { this.type = type; this.name = name; this.age = age; this.sex = sex; } Animal.prototype.print = function () { console.log("种类", this.type); console.log("名字", this.name); console.log("年龄", this.age); console.log("性别", this.sex); } // 面向对象中, 上面的属性和方法的定义,统称为一个类 const a = new Animal("狗", "旺财", 3, "男") a.print(); 1. 属性和原型方法定义分离, 降低了可读性 2. 原型成员可以被枚举, 方法可以被变量 3. 默认情况下,构造函数仍然可以当作普通函数使用 类的特点: class Animal { constructor(type, name, age, sex) { this.type = type; this.name = name; this.age = age; this.sex = sex; } /** * @description: 打印方法 * @param : * @return: */ print() { console.log("种类", this.type); console.log("名字", this.name); console.log("年龄", this.age); console.log("性别", this.sex); } } const a = new Animal("狗", "旺财", 3, "男") a.print(); 1. 类声明不会被提升, 与let 和const 一样,存在暂时性死区 2. 类中的所有代码均在严格模式下执行 3. 类的所有方法都是不可枚举 4. 类的所有方法内部都无法当作构造函数使用 5. 类的构造器必须使用 new 来调用 类的其他书写方式: 1. 可计算的成员名: 如: cosnt printName = "print"; const obj = { print(){ console.log('打印'); } } 调用方式: obj.[printName]() 就是等于obj.print() 2. getter 和 setter 方法 es5 中可以使用 Object.defineProperty() 可以定义某个对象成员属性的读取和设置 es5以前使用函数来给一个对象来赋值或者取值 使用getter和setter控制的属性不在原型上 使用方法: 直接在函数前面加上get set 构造器里面还是原来的写法 3.静态成员: 构造函数本身的成员, 通过new 出来的成员叫做实例原型; 例如: 上面的Animal.abc = "abc" 这个叫做静态成员 而new 出来的东西叫做实例成员 使用static 定义的成员,就是静态成员 4. 字段初始化器(es7): 写成员的时候可以直接赋值 如: class Test{ static a = 1; b = 2; c = 3 } 相当于: class Test{ constructor(){ this.a = 1; this.b = 2; this.c = 3; } } 注意: 1. 使用static的字段初始化器,添加的是静态成员 2. 没有使用static的字段初始化器, 添加的成员位于对象上 3. 箭头函数使用初始化器,存在对象上面,不在原型上 可以通过console.dir(类名) 5. 表达式: 如: const A = class{ //匿名类,表达式 } 6. 装饰器(es7): 提示方法以及过时,因为有的方法更新过程,会在其他地方使用,所以提示后面开发者 使用装饰器标记方法过期了 语法: @+ 名称 如: class Test { @Obsolete print(){ } } // 现在用不了,需要使用babel或者用typescript function Obsolete(target, methodName, descriptor){ // target function Test // print // {value: function print(){},……} const oldFunc = descriptor.value; descriptor.value = function(...args){ console.warn(`${methodName}` 方法已经过时了) oldFunc.apply(this, args) } } es6类的继承: 如果两个类A和B,如果可以描述为:B是A, 则A和B形成继承关系 如果B是A,则: 1. B继承自A 2. A派生B 3. B是A的子类 4. A是B的父类 如果A是B的父类,则B会自动拥有A的所有实例成员 es6以前通过, call() 来实现继承 如: // 以下代码实现了了一个动物的方法,要实现狗继承于动物 function Animal(type, name, age, sex){ this.type = type; this.name = name; this.age = age; this.sex = sex; } Animal.prototype.print = function(){ console.log(this); } function Dog(name, age, sex){ // 这么写可以实现属性的继承,但是Dog里面没有动物类上的打印方法; // 原因: 动物的原型上才有打印的方法, 但是狗的只是使用了动物的构造函数。 // 但是动物的原型并没有继承过来, 所以要使狗的隐式原型要使用动物的原型 Animal.call(this, "犬类", name, age, sex); } // 这样就形成了继承关系了 Object.setPrototypeOf(Dog.prototype, Animal.prototype); es6的做法如下: extends: 继承 super: 1. 直接当作函数来调用,表示父类构造函数 2. 如果当作对象使用,表示调用父类的方法super.print() 例如: class Animal { constructor(type, name, age, sex) { this.type = type; this.name = name; this.age = age; this.sex = sex; } print() { console.log(this) } } class Dog extends Animal{ constructor(name, sex, age){ super("犬类", name, age, sex); } } 注意: es6要求,如果定义了constructor,并且该类式子类,则必须在constructor的第一行手动调用父类的构造函数 如果子类不写constructor,则会有默认的构造器,该构造器需要的参数和父类一模一样,并且调用父类的构造器 用js制作抽象类: 该类不能被实例话,只能被继承 this 执行具体的类