es6中"类"--class的方式创建对象和es5中正常用法比较
来源:互联网 发布:美国人口普查历年数据 编辑:程序博客网 时间:2024/05/16 14:32
JavaScript语言的传统方法是通过构造函数,定义并生成新对象。下面是一个例子。(可以是工厂模式,构造函数模式,组合模式优缺点自己可以在网上查找)
function Point(x,y){
this.x=x;
this.y = y;
}
Point.prototype.toString = function(){
return '('+this.x+','+this.y+')';
}
var p= new Point(1,2);
在es6中使用类的方式定义:
//定义类class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; }}
哈哈哈,1.类Point中方法之间不用,号隔开,方法不用function进行定义,构造函数的prototype
属性,在ES6的“类”上面继续存在。事实上,类的所有方法都定义在类的prototype
属性上面。
class Point { constructor(){ // ... } toString(){ // ... } toValue(){ // ... }}// 等同于Point.prototype = { toString(){}, toValue(){}};
2.类的内部所有定义的方法,都是不可枚举的(但是在es5中prototype的方法是可以进行枚举的)3.每一个类中都有一个constructor方法该方法返回实例对象
4.
类的构造函数,不使用new
是没法调用的,会报错。这是它跟普通构造函数的一个主要区别,后者不用new
也可以执行。
二、用类进行实例和用普通的构造函数进行实例:
1、用类进行实例的必须使用new否则就会报错
2、与ES5一样,实例的属性除非显式定义在其本身(即定义在this
对象上),否则都是定义在原型上(即定义在class
上)。
3、与ES5一样,类的所有实例共享一个原型对象。
4、Class不存在变量提升(hoist),这一点与ES5完全不同
new Foo(); // ReferenceErrorclass Foo {}
上面代码中,Foo
类使用在前,定义在后,这样会报错,因为ES6不会把类的声明提升到代码头部。这种规定的原因与下文要提到的继承有关,必须保证子类在父类之后定义。
{ let Foo = class {}; class Bar extends Foo { }}
上面的代码不会报错,因为Bar
继承Foo
的时候,Foo
已经有定义了。但是,如果存在class
的提升,上面代码就会报错,因为class
会被提升到代码头部,而let
命令是不提升的,所以导致Bar
继承Foo
的时候,Foo
还没有定义。
2、Class的继承 § ⇧
constructor
方法中调用super
方法,否则新建实例时会报错。这是因为子类没有自己的this
对象,而是继承父类的this
对象,然后对其进行加工。如果不调用super
方法,子类就得不到this
对象。this
,然后再将父类的方法添加到this
上面(Parent.apply(this)
)。ES6的继承机制完全不同,实质是先创造父类的实例对象this
(所以必须先调用super
方法),然后再用子类的构造函数修改this
。另一个需要注意的地方是,在子类的构造函数中,只有调用super
之后,才可以使用this
关键字,否则会报错。这是因为子类实例的构建,是基于对父类实例加工,只有super
方法才能返回父类实例。
class Point { constructor(x, y) { this.x = x; this.y = y; }}class ColorPoint extends Point { constructor(x, y, color) { this.color = color; // ReferenceError super(x, y); this.color = color; // 正确 }}
上面代码中,子类的constructor
方法没有调用super
之前,就使用this
关键字,结果报错,而放在super
方法之后就是正确的。
super.print.call(this)
类的prototype属性和__proto__属性 § ⇧
大多数浏览器的ES5实现之中,每一个对象都有__proto__
属性,指向对应的构造函数的prototype属性。Class作为构造函数的语法糖,同时有prototype属性和__proto__
属性,因此同时存在两条继承链。
(1)子类的__proto__
属性,表示构造函数的继承,总是指向父类。
(2)子类prototype
属性的__proto__
属性,表示方法的继承,总是指向父类的prototype
属性。
class A {}class B extends A {}B.__proto__ === A // trueB.prototype.__proto__ === A.prototype // true
上面代码中,子类B
的__proto__
属性指向父类A
,子类B
的prototype
属性的__proto__
属性指向父类A
的prototype
属性。
这样的结果是因为,类的继承是按照下面的模式实现的。
实例的__proto__属性
子类实例的__proto__属性的__proto__属性,指向父类实例的__proto__属性。也就是说,子类的原型的原型,是父类的原型。
原生构造函数的继承
原生构造函数是指语言内置的构造函数,通常用来生成数据结构。ECMAScript的原生构造函数大致有下面这些。
- Boolean()
- Number()
- String()
- Array()
- Date()
- Function()
- RegExp()
- Error()
- Object()
以前,这些原生构造函数是无法继承的,比如,不能自己定义一个Array
的子类。
function MyArray() { Array.apply(this, arguments);}MyArray.prototype = Object.create(Array.prototype, { constructor: { value: MyArray, writable: true, configurable: true, enumerable: true }});
上面代码定义了一个继承Array的MyArray
类。但是,这个类的行为与Array
完全不一致。
var colors = new MyArray();colors[0] = "red";colors.length // 0colors.length = 0;colors[0] // "red"
之所以会发生这种情况,是因为子类无法获得原生构造函数的内部属性,通过Array.apply()
或者分配给原型对象都不行。原生构造函数会忽略apply
方法传入的this
,也就是说,原生构造函数的this
无法绑定,导致拿不到内部属性。
this
,再将父类的属性添加到子类上,由于父类的内部属性无法获取,导致无法继承原生的构造函数。比如,Array构造函数有一个内部属性[[DefineOwnProperty]]
,用来定义新属性时,更新length
属性,这个内部属性无法在子类获取,导致子类的length
属性行为不正常。ES6允许继承原生构造函数定义子类,因为ES6是先新建父类的实例对象this
,然后再用子类的构造函数修饰this
,使得父类的所有行为都可以继承。下面是一个继承Array
的例子。
class MyArray extends Array { constructor(...args) { super(...args); }}var arr = new MyArray();arr[0] = 12;arr.length // 1arr.length = 0;arr[0] // undefined
上面代码定义了一个MyArray
类,继承了Array
构造函数,因此就可以从MyArray
生成数组的实例。这意味着,ES6可以自定义原生数据结构(比如Array、String等)的子类,这是ES5无法做到的。
上面这个例子也说明,extends
关键字不仅可以用来继承类,还可以用来继承原生的构造函数。因此可以在原生数据结构的基础上,定义自己的数据结构
- es6中"类"--class的方式创建对象和es5中正常用法比较
- 关于ES5中的prototype与ES6中class继承的比较
- React: ES5 和 ES6 比较
- React Native 中 ES6+ 和 ES5 语法比较
- js中es5类的创建继承与es6中类的创建继承
- 创建Class对象的4中方式
- ES5和ES6中对于继承的实现方法
- 图解说明ES5和ES6中继承的区别
- es5和es6中封装继承的不同
- React.js中ES6 和 ES5写法的一些差别
- JavaScript和ES6中字符串、数组对象的比较
- es6与es5 中this的区别
- ES6 Class的用法
- JavaScript创建对象—从es5到es6
- ES6与ES5继承比较
- Silverlight在IE中无法显示但在Firefox中正常的原因和解决办法
- ES6和ES5中的遍历
- ES6和ES5特性对比
- C++作业5
- Java将远程服务器上的文件经过本地服务器中转后输出至前端
- poj 1236 Network of Schools
- Emmet(ZenCoding)语法(一)
- git的基础使用
- es6中"类"--class的方式创建对象和es5中正常用法比较
- [硬件]树莓派2代无显示器安装系统(固定IP+VNC开机自启动)
- 纯原生js 贪吃蛇(锻炼你逻辑思维)
- 问号
- 微信公众号开发---群发消息
- 如何编写linux下nand flash驱动
- iOS 弹性动画之弹出分享菜单的实现
- jquery根据name属性查找
- Android O 行为变更