学习es6中class——整合阮一峰教程、MDN
导语
//定义类
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
定义class
类声明
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
var obj = new Myclass(); //报错
class Myclass (){ }
{
let B = class {}; // let 声明 不存在函数提升
class A extends B { //如果存在类哈函数提升的话,这行会提升到第一行,父亲还没声明,儿子怎么继承?
}
}
class f1 {};
class f1 {};
var f2 = class {};
class f2 {}; // 报错了
class f3 {};
var f3 = class {}; // 报错了
var f4 = class {};
var f4 = class {}; // 如果两个函数表达式重名了,那么不会报错
类表达式
var myClass = class [className] [extends] {
// class body
}
// 方式一
const MyClass = class {};
// 方式二:给出类名
const MyClass = class Me {
getClassName() {
return Me.name;
}
};
var Foo = class {
constructor() {}
bar() {
return 'Hello World!';
}
};
var instance = new Foo();
instance.bar(); // "Hello World!"
Foo.name; // "Foo"
var Foo = class NamedFoo {
constructor() {}
whoIsThere() {
return NamedFoo.name;
}
}
var bar = new Foo();
bar.whoIsThere(); // "NamedFoo"
NamedFoo.name; // ReferenceError: NamedFoo is not defined
Foo.name; // "NamedFoo"
let person = new class {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}('Zhang San');
person.sayName(); // Zhang San
类体和方法定义
构造器(constructor方法)
一个类只能拥有一个名为constructor
的方法(否则会报错),一个类的 constructor 方法只有在实例化的时候被调用。
如果没有显式定义constructor
方法,这个方法会被默认添加,即,不管有没有显示定义,任何一个类都有constructor
方法。
子类必须在constructor方法中调用super
方法,否则新建实例时会报错。因为子类没有自己的this
对象,而是继承父类的this
对象,然后对其进行加工,如果不调用super
方法,子类就得不到this
对象。
class Point {}
class ColorPoint extends Point {
constructor() {}
}
let cp = new ColorPoint(); // ReferenceError
ColorPoint
继承了父类Point
,但是它的构造函数没有调用super
方法,导致新建实例时报错。
原型方法
定义类的方法时,方法名前面不需要加上function
关键字。另外,方法之间不需要用逗号分隔,加了会报错。
class Bar {
constructor() {}
doStuff() {}
toString() {}
toValue() {}
}
Bar.prototype = {
doStuff() {},
toString() {},
toValue() {}
};
prototype
上面,所以类的新方法可以添加在prototype
对象上面。Object.assign
方法可以很方便地一次向类添加多个方法。
class Point {
constructor() {
// ...
}
}
Object.assign(Point.prototype, {
toString() {},
toValue() {}
});
class Point {
constructor(x, y) {
// ...
}
toString() {
return '(' + x + ', ' + y + ')';
}
}
Object.keys(Point.prototype); // []
Object.getOwnPropertyNames(Point.prototype); // ["constructor", "toString"]
Object.getOwnPropertyDescriptor(Point, 'toString');
// Object {writable: true, enumerable: false, configurable: true}
静态方法
static
关键字用来定义类的静态方法。静态方法是指那些不需要对类进行实例化,使用类名就可以直接访问的方法。静态方法经常用来作为工具函数。
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
static distance(a, b) {
const dx = a.x - b.x;
const dy = a.y - b.y;
return Math.sqrt(dx*dx + dy*dy);
}
}
const p1 = new Point(5, 5);
const p2 = new Point(10, 10);
console.log(Point.distance(p1, p2));
静态方法不可以被实例继承,是通过类名直接调用的。但是,父类的静态方法可以被子类继承。
class Foo {
static classMethod() {
return 'hello';
}
}
class Bar extends Foo {
}
Bar.classMethod(); // "hello"
extends关键字
extends
关键字用于实现类之间的继承。子类继承父类,就继承了父类的所有属性和方法。 extends
后面只可以跟一个父类。
class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y); // 调用父类的constructor(x, y)
this.color = color;
}
toString() {
return this.color + ' ' + super.toString(); // 调用父类的toString()
}
}
extends
关键字不能用于继承一个对象,如果你想继承自一个普通的对象,你必须使用 Object.setPrototypeof ( )
es5 的继承和 es6 的继承
//先来个父类,带些属性
function Super(){
this.flag = true;
}
//为了提高复用性,方法绑定在父类原型属性上
Super.prototype.getFlag = function(){
return this.flag;
}
//来个子类
function Sub(){
this.subFlag = false;
}
//实现继承
Sub.prototype = new Super;
//给子类添加子类特有的方法,注意顺序要在继承之后
Sub.prototype.getSubFlag = function(){
return this.subFlag;
}
//构造实例
var es5 = new Sub;
function Super(){
this.flag = true;
}
Super.prototype.getFlag = function(){
return this.flag; //继承方法
}
function Sub(){
this.subFlag = flase
Super.call(this) //继承属性
}
Sub.prototype = new Super;
var obj = new Sub();
Sub.prototype.constructor = Sub;
Super.prototype.getSubFlag = function(){
return this.flag;
}
Sub.prototype.constructor = Sub;
function _inherits(subClass, superClass) {
// 确保superClass为function
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
// 把子类.prototype 继承了父类.prototype(new 父类), 同时把子类prototype的constructor进行了重写;
// 给subClass添加constructor这个属性
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
// 将父类设为子类的prototype
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}
子类.prototype = new 父类
function Car (desc) {
this.desc = desc;
this.color = "red";
}
Car.prototype = {
getInfo: function() {
return 'A ' + this.color + ' ' + this.desc + '.';
}
};
//instantiate object using the constructor function
var car = Object.create(Car.prototype);
car.color = "blue";
alert(car.getInfo()); //displays 'A blue undefined.' ??! // 看见了吧,只会继承方法,不能继承属性
var Car2 = Object.create(null); //this is an empty object, like {}
Car2.prototype = {
getInfo: function() {
return 'A ' + this.color + ' ' + this.desc + '.';
}
};
var car2 = Object.create(Car2.prototype, {
//value properties
color: { writable: true, configurable:true, value: 'red' },
//concrete desc value
rawDesc: { writable: false, configurable:true, value: 'Porsche boxter' },
// data properties (assigned using getters and setters)
desc: {
configurable:true,
get: function () { return this.rawDesc.toUpperCase(); },
set: function (value) { this.rawDesc = value.toLowerCase(); }
}
});
car2.color = 'blue';
alert(car2.getInfo()); //displays 'A RED PORSCHE BOXTER.'
var _this = _possibleConstructorReturn(this, (b.__proto__ || Object.getPrototypeOf(b)).call(this));
class A extends Object {
}
A.__proto__ === Object // true
A.prototype.__proto__ === Object.prototype // true
class A {
}
A.__proto__ === Function.prototype // true
A.prototype.__proto__ === Object.prototype // true
class C extends null {
constructor() { return Object.create(null); }
}
两条继承链
class A extends B {}
A.__proto__ === B; //继承属性
A.prototype.__proto__ === B.prototype; //继承方法
子类.prototype = Object.create (父类.prototype) // 相当于 new 父类
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
var p1 = new Point(2,3);
var p2 = new Point(3,2);
p1.__proto__ === p2.__proto__
var p1 = new Point(2,3);
var p2 = new Point(3,2);
p1.__proto__.printName = function () { return 'Oops' };
p1.printName() // "Oops"
p2.printName() // "Oops"
var p3 = new Point(4,2);
p3.printName() // "Oops"
super 关键字
super
关键字可以用来调用其父类的构造器或方法。super 作为方法的时候,必须在 constructor 中调用,并且只能在 constructor 里面被调用
class Cat {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
class Lion extends Cat {
speak() {
super.speak();
console.log(this.name + ' roars.');
}
}
class A {
p() {
return 2;
}
}
class B extends A {
constructor() {
super();
console.log(super.p()); // 2
}
}
let b = new B();
class A {
constructor() {
this.x = 1;
}
print() {
console.log(this.x);
}
}
class B extends A {
constructor() {
super();
this.x = 2;
}
m() {
super.print();
}
}
let b = new B();
b.m() // 2
class A {
constructor() {
this.x = 1;
}
}
class B extends A {
constructor() {
super();
this.x = 2;
super.x = 3;
console.log(super.x); // undefined
console.log(this.x); // 3
}
}
let b = new B();
class Parent {
static myMethod(msg) {
console.log('static', msg);
}
myMethod(msg) {
console.log('instance', msg);
}
}
class Child extends Parent {
static myMethod(msg) {
super.myMethod(msg);
}
myMethod(msg) {
super.myMethod(msg);
}
}
Child.myMethod(1); // static 1
var child = new Child();
child.myMethod(2); // instance 2
class A {}
class B extends A {
constructor() {
super();
console.log(super); // 报错
}
}
类的Getter和Setter方法
与ES5一样,在类内部可以使用get
和set
关键字,对某个属性设置取值和赋值方法。
class Foo {
constructor() {}
get prop() {
return 'getter';
}
set prop(val) {
console.log('setter: ' + val);
}
}
let foo = new Foo();
foo.prop = 1;
// setter: 1
foo.prop;
// "getter"
prop
属性有对应 的赋值和取值方法,因此赋值和读取行为都被自定义了。 存值和取值方法是设置在属性的descriptor对象上的。
var descriptor = Object.getOwnPropertyDescriptor(Foo.prototype, 'prop');
"get" in descriptor // true
"set" in descriptor // true
prop
属性的描述对象上的,这与ES5一致。
类的Generator方法
如果类的某个方法名前加上星号(*
),就表示这个方法是一个Generator函数。
class Foo {
constructor(...args) {
this.args = args;
}
* [Symbol.iterator]() {
for (let arg of this.args) {
yield arg;
}
}
}
for (let x of new Foo('hello', 'world')) {
console.log(x);
}
// hello
// world
for...of
循环会自动调用这个遍历器。
new.target属性
function Person(name) {
if (new.target !== undefined) {
this.name = name;
} else {
throw new Error('必须使用new生成实例');
}
}
// 另一种写法
function Person(name) {
if (new.target === Person) {
this.name = name;
} else {
throw new Error('必须使用new生成实例');
}
}
var person = new Person('张三'); // 正确
var notAPerson = Person.call(person, '张三'); // 报错
class Rectangle {
constructor(length, width) {
console.log(new.target === Rectangle);
// ...
}
}
class Square extends Rectangle {
constructor(length) {
super(length, length); // 相当于执行父类中的constructor,
}
}
var obj = new Square(3); // 输出 false
class Shape {
constructor() {
if (new.target === Shape) {
throw new Error('本类不能实例化'); // 抛出一个错误
}
}
}
class Rectangle extends Shape {
constructor(length, width) {
super();
// ...
}
}
var x = new Shape(); // 报错
var y = new Rectangle(3, 4); // 正确
转载于:https://www.cnblogs.com/dujuncheng/p/6907980.html
学习es6中class——整合阮一峰教程、MDN相关推荐
- ES6专题——整理自阮一峰老师的ECMAScript 6入门
这里我仅仅是记录了那些我认为值得注意的ES6知识点,详细版请挪步https://es6.ruanyifeng.com/#docs/let let和const命令 let声明的变量只在它所在的代码块有效 ...
- 《es6标准入门》 阮一峰
2 let和const命令 2.1 let命令 2.1.1 基本用法 2.1.2 不存在变量提升 2.1.3 暂时性死区 2.1.4 不允许重复声明 2.2 块级作用域 2.2.1 为什么需要块级作用 ...
- 学习react之React 入门(阮一峰教程笔记)
一 react.js react-dom.js Brower.js react.js 核心库 react-dom.js提供dom方法 Brower.js JSX语法--->JS语法 服务器 $ ...
- 阮一峰php博客,在PHP语言中使用JSON – 阮一峰的网络日志
目前,JSON已经成为最流行的数据交换格式之一,各大 我写过一篇<数据类型和JSON格式>,探讨它的设计思想.今天,我想总结一下PHP语言对它的支持,这是开发 从5.2版本开始,PHP原生 ...
- 程序员的自我修养--读阮一峰《如何变得有思想》有感
前言 年前无意浏览到阮一峰的网络博客(链接),一发不可收拾,从那以后一直追着拜读其博客,并看到了其在网站上的广告(暂且称为广告)<如何变得有思想>,果断买来拜读,但是一直忙于各种事情,最近 ...
- 通过这个免费的,由23部分组成的互动课程,学习ES6 +
JavaScript is undoubtedly one of the most popular programming languages in the world. It's used almo ...
- ES6 标准入门(第二版)阮一峰学习
现在前端环境中,每一位程序员都要求熟练ES6语法,但是大部分ES6的文档都不太完整,接下来的时间,我将为童鞋们分享阮一峰老师第二版的ES6标准.让我们一起来学习一下!!! 本期先说一下学习的目录 1: ...
- 前端知乎:关于阮一峰博客《学习Javascript闭包》章节中最后两个思考题
阮一峰博客:<学习Javascript闭包>章节中最后有个思考题: 如果你能理解下面两段代码的运行结果,应该就算理解闭包的运行机制了. 代码片段一 var name = "The ...
- 【ES6】阮一峰ES6学习(六) Proxy
Proxy 1. 前言 2. 使用 3. Proxy 实例方法 1. get()方法 2. set()方法 3. apply()方法 4. 为什么要存在Proxy? 两者对比 1. 前言 es6中全新 ...
最新文章
- 2.easyui 控件取值方式
- 问题解决——使用CriticalSection后 0xXXXXXXXX处最可能的异常: 0xC0000005: 写入位置 0x00000014 时发生访问冲突
- spring bean中scope=prototype“的作用
- 关于extjs中动态添加TabPanel的tab项并以iframe显示的整理(转)
- 必背42个单词_高中英语必背100个常考单词,考试必考
- 实现公告板和本周热卖功能
- Bash脚本15分钟进阶教程-转
- adobe dreamweaver cs6 css,Adobe Dreamweaver CS6
- 特征值分解:特征值,特征向量,特征向量矩阵
- java 本地连接状态_本地连接受限制
- 查询和01号的同学学习的课程完全相同的其他同学的信息的优化
- 2022中国新时代100大建筑公布,重庆来福士、北京大兴机场、港珠澳大桥等杰出工程入选 | 美通社头条...
- 平面设计中负空间的意思是什么?如何设计?
- 从零到一写一个完整的 Compose 版本的天气
- mini2440----keil for AMR之IIC读写EEPROM(AT24C08)
- Android群英传笔记——第十章:Android性能优化
- TFT供电电路(VCOM/VGL/VGH/AVDD)设计原理
- 【计算机科学基础】翻译、编译、解释、汇编
- web前端——网页设计
- 智慧园区信息化解决方案,未来园区发展新方向
热门文章
- Spring Boot缓存实战 默认Cache(ConcurrentMapCacheManager)
- luoguP3799 妖梦拼木棒
- 计算机配件模拟,电脑装机模拟各配件跑分及计算公式分享
- oracle生僻字解决方案
- htc 8x android,htc 8x的usb驱动下载
- 必读的AI和深度学习博客
- 计算机识别不了佳能打印机,佳能IP4200打印机“无法识别墨水盒”解决办法
- 数加加众包:奔驰“哭诉维权”美女硕士,你“不要脸”的样子真的很美
- ORA-12899: value too large for column 问题解决
- USACO--Milking Cows (C语言)挤奶牛