类的由来
function Point(x, y) {
this.x = x;
this.y = y
}
Point.prototype.toString = function () {
return '(' + this.x + ', ' + this.y + ')'
}
var p = new Point(2,3)
console.log('p',p)
class Point2 {
constructor(x,y){
this.x = x;
this.y = y
}
toString() {
return '(' + this.x + ', ' + this.y + ')'
}
}
console.log(typeof Point2);
console.log(Point2.prototype.constructor == Point2)
console.log(Object.keys(Point2.prototype))
console.log(Object.keys(Point.prototype))
constructor() 方法
class Point {
}
class Point {
constructor(){
return Object.create(null)
}
}
p = new Point()
console.log(p instanceof Point)
类的实例
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
var point = new Point(2, 3);
point.toString()
point.hasOwnProperty('x')
point.hasOwnProperty('y')
point.hasOwnProperty('toString')
point.__proto__.hasOwnProperty('toString')
var p1 = new Point(2,3);
var p2 = new Point(3,2);
p1.__proto__ === p2.__proto__
实例属性新写法
class Point {
_count = 0
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
取值函数(getter)和存值函数(setter)
class MyClass {
constructor(){
}
get prop(){
return 'getter'
}
set prop(value){
console.log('setter'+value)
}
}
var p = new MyClass()
console.log(p.prop)
p.prop = 123
属性表达式
let methodName = 'getArea';
class Square {
constructor(length) {
}
[methodName]() {
}
}
Class 表达式
const MyClass = class Me {
getClassName() {
return Me.name;
}
};
const MyClass = class { };
let person = new class {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}('张三');
person.sayName();
静态方法
class Foo {
static classMethod() {
return 'hello';
}
}
Foo.classMethod()
var foo = new Foo();
foo.classMethod()
class Foo {
static bar() {
this.baz();
}
static baz() {
console.log('hello');
}
baz() {
console.log('world');
}
}
Foo.bar()
class Foo {
static classMethod() {
return 'hello';
}
}
class Bar extends Foo {
}
Bar.classMethod()
class Foo {
static classMethod() {
return 'hello';
}
}
class Bar extends Foo {
static classMethod() {
return super.classMethod() + ', too';
}
}
Bar.classMethod()
静态属性
class Foo {
static str = '测试'
}
Foo.prop = 1
console.dir(Foo)
私有属性和私有方法
class IncreasingCounter {
#count = 0;
get value() {
console.log('Getting the current value!');
return this.#count;
}
increment() {
this.#count++;
}
#sum() {
return 'sum';
}
}
const counter = new IncreasingCounter();
console.log(counter.value)
counter.#count
counter.#count = 42
class Counter {
#xValue = 0;
constructor() {
console.log(this.#x);
}
get #x() { return this.#xValue; }
set #x(value) {
this.#xValue = value;
}
}
const counter = new Counter();
class FakeMath {
static PI = 22 / 7;
static #totallyRandomNumber = 4;
static #computeRandomNumber() {
return FakeMath.#totallyRandomNumber;
}
static random() {
console.log('I heard you like random numbers…')
return FakeMath.#computeRandomNumber();
}
}
FakeMath.PI
FakeMath.random()
FakeMath.#totallyRandomNumber
FakeMath.#computeRandomNumber()
static静态块
class C {
static x;
static y;
static z;
constructor() {
console.log('constructor')
}
static {
console.log('static')
try {
const obj = doSomethingWith(this.x);
this.y = obj.y;
this.z = obj.z;
}
catch {
this.y = 1;
this.z = 2;
this.x;
C.x;
}
}
}
var c = new C()
类的注意点
严格模式
类和模块的内部,默认就是严格模式
不存在提升
new Foo();
class Foo {}
this指向
类的方法内部如果含有this,它默认指向类的实例。但是,必须非常小心,一旦单独使用该方法,很可能报错。
class Logger {
printName(name = 'there') {
this.print(`Hello ${name}`);
}
print(text) {
console.log(text);
}
}
const logger = new Logger();
const { printName } = logger;
printName();
解决方法
在构造函数中绑定this
class Logger {
constructor() {
this.printName = this.printName.bind(this);
}
}
另一种解决方法是使用箭头函数。
new.target 属性
返回new命令作用于的那个构造函数。如果构造函数不是通过new命令或Reflect.construct()调用的,
new.target会返回undefined
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 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);