只要你开始思考、开始行动,你就已经走上了一条必然不易,但也充满希望的路途了。
今日学习内容 1、JS 红皮书 P254-256 第八章:对象、类与面向对象编程
今日笔记 1、类的语法可以非常方便地定义应该存在于实例上的成员、应该存在于原型上的成员,以及应该存在于类本身的成员。
实例成员: 每次通过 new 调用类标识符时,都会执行类构造函数。在这个函数内部,可以为新创建的实例(this)添加“自有”属性。至于添加什么样的属性,则没有限制。另外,在构造函数执行完毕后,仍然可以给实例继续添加新成员。每个实例都对应一个唯一的成员对象,这意味着所有成员都不会在原型上共享:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Person { constructor ( ) { this .name = new String ("Jack" ); this .sayName = () => console .log (this .name ); this .nicknames = ["Jake" , "J-Dog" ]; } } let p1 = new Person (), p2 = new Person (); p1.sayName (); p2.sayName (); console .log (p1.name === p2.name ); console .log (p1.sayName === p2.sayName ); console .log (p1.nicknames === p2.nicknames ); p1.name = p1.nicknames [0 ]; p2.name = p2.nicknames [1 ]; p1.sayName (); p2.sayName ();
原型方法与访问器: 为了在实例间共享方法,类定义语法把在类块中定义的方法作为原型方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 class Person { constructor ( ) { this .locate = () => console .log ("instance" ); } locate ( ) { console .log ("prototype" ); } } let p = new Person ();p.locate (); Person .prototype .locate (); class Person { name : "Jake" ; } const symbolKey = Symbol ("symbolKey" );class Person { stringKey ( ) { console .log ("invoked stringKey" ); } [symbolKey]() { console .log ("invoked symbolKey" ); } ["computed" + "Key" ]() { console .log ("invoked computedKey" ); } } let p = new Person ();p.stringKey (); p[symbolKey](); p.computedKey (); class Person { set name (newName ) { this .name_ = newName; } get name () { return this .name_ ; } } let p = new Person ();p.name = "Jake" ; console .log (p.name );
静态类方法: 可以在类上定义静态方法。这些方法通常用于执行不特定于实例的操作,也不要求存在类的实例。与原型成员类似,静态成员每个类上只能有一个。 静态类成员在类定义中使用 static 关键字作为前缀。在静态成员中,this 引用类自身。其他所有约定跟原型成员一样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class Person { constructor ( ) { this .locate = () => console .log ("instance" , this ); } locate ( ) { console .log ("prototype" , this ); } static locate ( ) { console .log ("class" , this ); } } let p = new Person ();p.locate (); Person .prototype .locate (); Person .locate (); class Person { constructor (age ) { this .age_ = age; } sayAge ( ) { console .log (this .age_ ); } static create ( ) { return new Person (Math .floor (Math .random () * 100 )); } } console .log (Person .create ());
非函数原型和类成员: 虽然类定义并不显式支持在原型或类上添加成员数据,但在类定义外部,可以手动添加:
1 2 3 4 5 6 7 8 9 10 11 class Person { sayName ( ) { console .log (`${Person.greeting} ${this .name} ` ); } } Person .greeting = 'My name is' ;Person .prototype .name = 'Jake' ; let p = new Person (); p.sayName ();
注意 类定义中之所以没有显式支持添加数据成员,是因为在共享目标(原型和类)上添加可变(可修改)数据成员是一种反模式。一般来说,对象实例应该独自拥有通过 this引用的数据。