JS笔记之JS类(一)
在日常的开发中,京城需要构建许多类型相同的对象,例如 Users, Goods ,我们可以使用构造器来完成这样的操作,但是在现代JS中可以是使用类这种方式来创建相同类型的对象。
1 类基本语法
1 2 3 4 5 6 7 8 9 10
| class MyClass { constructor() { ... } method1() { ... } method2() { ... } method3() { ... } ... } let user = new User()
|
new 会自动调用constructor
方法,因此可以在constructor
方法中初始化对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
let user = new User("John"); user.sayHi();
|
在python中创建类的方式也大同小异。
1 2 3 4 5 6 7 8 9 10 11 12
| class User:
def __init__(self, name): self.name = name
def say_hi(self): print(f"我的名字是:{self.name},Hi~")
if __name__ == '__main__': user = User('张三') user.say_hi()
|
在JS中当 new User(“john”)被调用时,代表一个新的对象被创建,constructor 使用给定的参数运行,并且将其赋值给this.name。
Tips:
类的方法之间没有逗号。
2 所以class到底是什么?
在JS中类是一种函数,class User(…) 实际上做了如下的事情:
- 创建一个名为User的函数,该函数称为类声明的结果,该函数的代码来自于constructor方法(如果不编写这个方法,那么就为空)。
- 存储类中的方法,例如 User.prototype.sayHi
3 class 不仅仅是语法糖
声明上述的User对象不使用类也可以声明一个同样的对象:`
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
function User(name) { this.name = name; }
User.prototype.sayHi = function () { alert(this.name); };
let user = new User("John"); user.sayHi();
|
虽然得到的结果基本相同,但是他们之间仍然存着巨大的差异。
通过class创建的函数具有特殊的内部属性标记。[[IsClassConstructor]]:true。
必须使用 new 来创建它。
1 2 3 4 5 6
| class User { constructor() { } }
console.log(typeof User); User();
|
类方法不可枚举,类定义将 prototype 中的所有的方法的描述符enumerable设置为fasle。
类总是使用 user strict , 在类构造中的代码都自动进入严格模式。
4 类表达式
类会像函数一样可以在另外一个表达式中被定义,被传递,返回,赋值等。如果类表达式有名字,那么该名字仅在类内部可见。且可以动态的创建类。
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
| let User = class { sayHi() { alert("Hello"); } };
let User = class MyClass { sayHi() { alert(MyClass); } };
new User().sayHi();
alert(MyClass);
function makeClass(phrase) { return class { sayHi() { alert(phrase); } }; }
let User = makeClass("Hello");
new User().sayHi();
|
5 getters/setters
类同样可能包括getters/setters,以及计算属性 (computed properties)等。
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
| class User {
constructor(name) { this.name = name; }
get name() { return this._name; }
set name(value) { if (value.length < 4) { alert("Name is too short."); return; } this._name = value; }
}
let user = new User("John"); alert(user.name);
user = new User("");
|
6 计算属性
计算属性的方法名称使用中括号声明:
1 2 3 4 5 6 7 8 9
| class User {
['say' + 'Hi']() { console.log("Hello"); }
}
new User().sayHi();
|
7 类字段
类字段是一种允许添加任何属性的语法,类字段的重要的不同之处在于他们会在每个对立对象中被设置好,而不是在User.prototype:
1 2 3 4 5 6 7
| class User { name = "John"; }
let user = new User(); console.log(user.name); console.log(User.prototype.name);
|
8 使用类字段实现绑定方法
在JS中具有动态的this,它取决于调用上下文,如果一个对象方法被传递到某处,或者在另一个上下文中被调用,则this不在是起对象的引用。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Button { constructor(value) { this.value = value; }
click() { console.log(this.value); } }
let button = new Button("hello");
setTimeout(button.click, 1000);
|
在函数进阶中的函数绑定中说明过这个情况,解决的方法有两种,一是使用包装器,二是将方法绑定到对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Button { constructor(value) { this.value = value; } click = () => { console.log(this.value); } }
let button = new Button("hello");
setTimeout(button.click, 1000);
|
在浏览器环境中,它对于进行事件监听尤为有用。
9 总结
类的基本语法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class MyClass { prop = value;
constructor(...) { }
method(...) { }
get something(...) { } set something(...) { }
[Symbol.iterator]() { } }
|
技术上来说,MyClass
是一个函数(我们提供作为 constructor
的那个),而 methods、getters 和 setters 都被写入了 MyClass.prototype
。