摘要:使用除关键字之外的方式调用构造函数会导致程序抛出错误。在类中修改类名会导致程序报错。与之等价的声明必须通过关键字调用构造函数不可使用关键字调用构造函数类表达式类表达式可以是被命名的或匿名的。类也是中的一等公民。
概述
class (类)作为对象的模板被引入,可以通过 class 关键字定义类。类简要说明
类的本质是function,是基本原型继承的语法糖。所以,JS中继承的模型是不会被改变的。
类既然是函数,那与函数有何不同呢?我们为什么要使用类呢?
有时间,先看一下MDN od
函数声明可以被提升,而类声明与let/const 声明类似,不能被提升,也就是在真正执行声明之前,它们会一直存在于临时死区中。
类声明中的所有代码将自动运行在严格模式下,而且无法强行让代码脱离严格模式。
类中的所有方法,都是不可枚举的。而普通自定义类型中,必须通过Object.defineProperty()方法来指定某方法不可枚举。
每个类都有一个[[Construct]]的内部方法,通过关键字new调用那些不含[[Construct]]的方法会导致程序抛出错误。
使用除关键字new之外的方式调用构造函数会导致程序抛出错误。
在类中修改类名会导致程序报错。
类声明首先class关键字,然后是类的名字,其它部分的语法,类似于对象字面量方法的简写形式,但不需要在各元素之间使用逗号分隔。
class HelloClass { constructor(greeting) { this.greeting = greeting; } sayGreeting(){ console.log(this.greeting); } } let hello = new HelloClass("Hello"); hello.sayGreeting(); // Hello console.log(hello instanceof HelloClass); // true console.log(hello instanceof Object); // true console.log(typeof HelloClass); // function console.log(typeof HelloClass.prototype.sayGreeting); // function
分析:
constructor为保留方法名,是用来构建对象的,不可用作其它用途。
函数定义之前,不需要添加function关键字。
类的属性不可被赋予新值,HelloClass.prototype是一个只可读类属性。
与之等价的ES5声明
let HelloClass = (function(){ "use strict"; const HelloClass = function(greeting) { if (typeof new.target === "undefined") { throw new Error("必须通过关键字new调用构造函数"); } this.greeting = greeting; Object.defineProperty(HelloClass.prototype, "sayGreeting", { value: function() { if (typeof new.target !== "undefined") { throw new Error("不可使用关键字new调用构造函数"); } console.log(this.greeting); }, enumerable: false, writable: true, configurable: true }); } return HelloClass; }()); let hello = new HelloClass("Hello"); hello.sayGreeting(); console.log(hello instanceof HelloClass); console.log(hello instanceof Object); console.log(typeof HelloClass); console.log(typeof HelloClass.prototype.sayGreeting);类表达式
类表达式可以是被命名的或匿名的。赋予一个命名类表达式的名称是类的主体的本地名称。和function的表达式类似,但不会像函数声名或和函数表达式一样被提升。
/* 匿名类 */ let Rectangle = class { constructor(height, width) { this.height = height; this.width = width; } }; console.log(typeof Rectangle); // function
/* 命名的类 */ let Rectangle = class Rectangle1 { constructor(height, width) { this.height = height; this.width = width; } }; console.log(typeof Rectange); // function console.log(typeof Rectange1); // undefined
在JS中,函数为一等“公民”,可以传入函数,也可以从函数中返回,还可以赋值给变量的值。类也是JS中的一等公民。
访问器- getter - setter
class Rectangle { // constructor constructor(height, width) { this.height = height; this.width = width; } // Getter get area() { return this.calcArea() } // Method calcArea() { return this.height * this.width; } } const square = new Rectangle(10, 10); console.log(square.area); // 100可计算成员
const methodName = "sayGreeting"; class HelloClass { constructor(greeting) { this.greeting = greeting; } [methodName]() { console.log(this.greeting); } } let hello = new HelloClass("Hello"); hello.sayGreeting(); // Hello hello[methodName](); // Hello
可计算访问器属性。
const propertyName = "greeting"; class HelloClass { constructor() { } get [propertyName]() { return this.greetingStr; } set [propertyName](value) { this.greetingStr = value; } } let hello = new HelloClass(); hello.greeting = "Hello"; console.log(hello.greeting);生成器方法
class NormClass { *createIterator() { yield 1; yield 2; yield 3; } } let instance = new NormClass(); let iterator = instance.createIterator(); console.log(iterator.next()); // { value: 1, done: false } console.log(iterator.next()); // { value: 2, done: false } console.log(iterator.next()); // { value: 3, done: false } console.log(iterator.next()); // { value: undefined, done: true }
为类定义默认迭代器。
class Collection { constructor() { this.items = []; } *[Symbol.iterator]() { yield *this.items.values(); } } var coll = new Collection(); coll.items.push(1); coll.items.push(2); coll.items.push(3); for (let i of coll) { console.log(i); } // 1 // 2 // 3静态成员
class Animal { speak() { return this; } static eat() { return this; } } let obj = new Animal(); console.log(obj.speak()); // Animal {} let speak = obj.speak; console.log(speak()); // undefined console.log(Animal.eat()); // class Animal let eat = Animal.eat; console.log(eat()); // undefined
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/105803.html
摘要:一自定义收集器陈杨将集合转换为集合存放相同元素二自定义收集器陈杨将学生对象按照存放从中间容器数据类型转换为结果类型数据类型一致若不一致抛出类型转换异常对中间容器数据结果类型进行强制类型转换多个线程同时操作同一个容器并行多线 一、自定义SetCustomCollector收集器 package com.java.design.Stream.CustomCollector; impor...
摘要:写这个文章其实主要是因为刚有个童鞋问了个问题正写的带劲安利的实现方式,结果还没写完无意发现问题被关闭了哎都写了一半了又不想放弃,就干脆写成文章问题主要就是把集合里的数据按照一定大小顺序平均分成若干组的问题,看起来挺简单的,不过我开始看到就想 写这个文章其实主要是因为刚有个童鞋问了个问题https://segmentfault.com/q/10...正写的带劲安利Java8的实现方式,结...
摘要:使用流收集数据分区分区是分组的特殊情况由一个谓词返回一个布尔值的函数作为分类函数,它称分区函数。这种情况下,累加器对象将会直接用作归约过程的最终结果。这也意味着,将累加器不加检查地转换为结果是安全的。 使用流收集数据 分区 分区是分组的特殊情况:由一个谓词(返回一个布尔值的函数)作为分类函数,它称分区函数。分区函数返回一个布尔值,这意味着得到的分组 Map 的键类型是 Boolean ...
摘要:构造函数继承在子类的构造函数中,通过或的形式,调用父类构造函数,以实现继承。所以,其实单独使用原型链继承或者借用构造函数继承都有自己很大的缺点,最好的办法是,将两者结合一起使用,发挥各自的优势。使指向自己而不是指向构造函数 原型链继承 子类的所有实例都共享着原型上的所有属性和方法。通过子类实例,可以访问原型上的属性,但是,不能重写原型上的属性。 //定义一个学生类 function S...
摘要:一收集器接口陈杨收集器接口汇聚操作的元素类型即流中元素类型汇聚操作的可变累积类型汇聚操作的结果类型接口一种可变汇聚操作将输入元素累积到可变结果容器中在处理完所有输入元素后可以选择将累积的结果转换为最终表示可选操作归约操作 一、Stream收集器 Collector接口 package com.java.design.java8.Stream; import com.java.desi...
阅读 2679·2021-11-18 10:02
阅读 3411·2021-09-28 09:35
阅读 2591·2021-09-22 15:12
阅读 749·2021-09-22 15:08
阅读 3085·2021-09-07 09:58
阅读 3469·2021-08-23 09:42
阅读 731·2019-08-30 12:53
阅读 2078·2019-08-29 13:51