为什么?
ES6中引入了类,类在java/c++等面向对象的编程语言常见,JS引入类是为了在日后使用js开发大型的应用程序,类本质是语法糖(语法上更加人性化)
以前写一个类
function User(name, age){ this.name = name; this.age = age; } // 静态方法 User.getClassName = function () { return 'User' }; // 为类添加公用方法,在原型对象上加 User.prototype.changeName = function (name) { this.name = name } User.prototype.changeAge = function (age) { this.age = age } // 为类添加取值函数与存值函数(都要写到原型对象上去) Object.defineProperty(User.prtotype, 'info', { get(){ return 'name:' + this.name + ' | age:' + this.age; } }); // 新建一个子类 function Manager(name, age, password){ User.call(this,name,age); // 也可以User.apply(this, arguments),意思是调用父类的构造函数,从而达到继承父类属性的效果,注意,只能继承父类实例属性,而继承不了父类的方法 this.password = password; } // 继承静态方法 Manager._proto_ = User; // 继承prototype方法(继承父类方法) Manager.prototype = User.prototype; // 也可以Manager.prototype = new User() // 添加新方法 Manager.prototype.changePassword = function(pwd){ this.password = password; }; // 验证是否能继承 var manager = new Manager('kkk', 22, '123'); manager.changeName('lighter'); console.log(manager.name) // 输出 lighter console.log(manager.info); // 输出 name:lighter | age:22
可以看出,以前ES5写一个类,虽然可以实现类的继承,但是很不优雅--!
ES6优雅写类
我们来注释上面的代码,一段一段地看它们又什么区别
//function User(name, age){ // this.name = name; // this.age = age; //} class User{ constructor(name, age){ this.name = name; this.age = age; } //// 静态方法 //User.getClassName = function () { // return 'User' //}; // 静态方法 User.getClassName = function () { return 'User'; } //// 为类添加公用方法,在原型对象上加 //User.prototype.changeName = function (name) { // this.name = name //} //User.prototype.changeAge = function (age) { // this.age = age //} // 为类添加公用方法,在原型对象上加 changeName(name) { this.name = name } changeAge(age) { this.age= age } //// 为类添加取值函数与存值函数(都要写到原型对象上去) //Object.defineProperty(User.prtotype, 'info', { // get(){ // return 'name:' + this.name + ' | age:' + this.age; // } //}); // 为类添加取值函数与存值函数(都要写到原型对象上去) get info() { return 'name:' + this.name + ' | age:' + this.age; } } // 新建一个子类 //function Manager(name, age, password){ // User.call(this,name,age); // this.password = password; //} //// 继承静态方法,原型链就是实力对象_proto_属性 //Manager._proto_ = User; //// 继承prototype方法 //Manager.prototype = User.prototype; class Manager extends User{ constructor(name, age, password){ super(name,age); this.password = password; } //// 添加新方法 //Manager.prototype.changePassword = function(pwd){ // this.password = password; //}; changePassword(password){ this.password = password } } // 然后下面的用法都是一样的。 // 验证是否能继承 var manager = new Manager('kkk', 22, '123'); manager.changeName('lighter'); console.log(manager.name) // 输出 lighter console.log(manager.info); // 输出 name:lighter | age:22
语法糖
注意,例如上面写的class 等概念,就是语法糖,它方便了我们写代码,使得代码更加地简洁,无论是class User ,还是class Manager,它们本质都是function
console.log(typeof User, typeof Manager); //输出 function function
简写继承
class I extends User { } var me = new I('psg', 23); console.log(me); //不报错,输出 I {name: 'psg', age: 23}
上面继承没加构造函数constructor,但是内部默认会加,上面的代码会变成下面这个样子:
class I extends User{ constructor(...arg){ super(...arg); } }
总结ES6继承的重点
1.继承时候,如果手写构造函数,那么在constructor块里面,第一行写super(....),因为它要先创建父类的对象,然后所有的方法(上面的changePassword)、属性(上面的password)都会加到父类创建的对象上。
2.使用super可以改变父类的方法,例如上面的Manager类,它继承User父类,现在我想改变从父类中继承的info方法,我加一点东西,使我Manager有别于父类,但是我还是调用同样父类方法的名字,这时我可以这样写:
class Manager extends User{ constructor(name, age, password){ super(name,age); this.password = password; } //// 添加新方法 //Manager.prototype.changePassword = function(pwd){ // this.password = password; //}; changePassword(password){ this.password = password } //使用super改写父类的方法 get info() { var info = super.info; // 注意!!这里的info没有() console.log(info); return info + '--new' } }
var manager = new Manager('kkk', 22, '123'); console.log(manager.info);
// 输出 name:lighter | age:22
// 输出 name:lighter | age:22---new
创建立即执行的类
'use strict' let user = new class User{ constructor(name){ this.name = name; } }('psg'); console.log(user); //输出 User {name: 'psg'}
不被提升
'use strict' var user = new User(); class User{ constructor(name){ this.name = name; } } console.log(user); //ReferenceError: User is not defined
-----完-----