手机版网站建设软件,wordpress删除模板文件夹,企业网站一般用什么域名,公司网站设计与实现的英文文献js 一直允许定义类。ES6新增了相关语法(包括class关键字)让创建类更容易。新语法创建的类和老式的类原理相同。js 的类和基于原型的继承机制与Java等语言中的类和继承机制有着本质区别。
1 类和原型
类意味着一组对象从同一个原型对象继承属性。因此#xff0c;原型对象是… js 一直允许定义类。ES6新增了相关语法(包括class关键字)让创建类更容易。新语法创建的类和老式的类原理相同。js 的类和基于原型的继承机制与Java等语言中的类和继承机制有着本质区别。
1 类和原型
类意味着一组对象从同一个原型对象继承属性。因此原型对象是类的核心特征。
用工厂函数创建和初始化该类的新实例
function range(from, to) {let r Object.create(range.methods);r.from from;r.to to;return r;
}range.methods {includes(x) {return this.from x x this.to;},*[Symbol.iterator]() {for (let x Math.ceil(this.from); x this.to; x)yield x;},toString() {return ( this.from ... this.to );},}let r range(1,3);
console.log(r.includes(2));
console.log(r ); // 调用的是toString()方法
console.log(r); // 打印对象本身而非调用toString()方法
console.log([...r])
2 类和构造函数
只有函数(不包括箭头函数、生成器函数和异步函数)对象才有prototype属性。
上面定义类的写法非习惯写法因为它没有定义构造函数。构造函数要使用new关键字调用会自动创建新对象因此构造函数本身只需初始化新对象的状态。构造函数调用的关键在于构造函数的prototype属性将被用作新对象的原型。
function Range(from,to) {this.from from;this.to to;
}// 原型属性名必须命名为prototype
Range.prototype {includes(x) {return this.from x x this.to;},*[Symbol.iterator]() {for (let x Math.ceil(this.from); x this.to; x)yield x;},toString() {return ( this.from ... this.to );}
}let r new Range(1,3);
console.log(r.includes(2));
console.log(r );
console.log(r)
console.log([...r])
2.1 instanceof
当且仅当两个对象继承同一个原型对象时它们才是同一个类的实例。instanceof 操作符用于检查某个对象是否是某个特定类的实例。
严格来讲instanceof操作符并非检查对象是否通过某个构造函数初始化而是检查对象是否继承了原型。不一定是直接继承
let prototype {}function Person() {}function Animal() {}let p new Person();console.log( p instanceof Person); // true
console.log( p instanceof Animal); // falsePerson.prototype prototype
Animal.prototype prototypelet p2 new Person()
console.log( p2 instanceof Person); // true
console.log( p2 instanceof Animal); // true
2.2 constructor 属性
prototype属性的值是一个对象其有一个不可枚举的constructor属性该属性的值就是prototype所属的函数对象:
let F function() {};
let p F.prototype;
let c p.constructor;
c F; //true
3 使用class关键字定义类
class关键字是在ES6才引入的。
使用class来定义类:
class Person {constructor(age) {this.age age;}showAge() {console.log(this.age);}}let p new Person(12);
p.showAge();let Animal class {constructor(name) {this.name name}showName() {console.log(this.name)}
}let a new Animal(大象);
a.showName()与函数声明不同类声明不会“提升”函数定义就像是会被提升到包含文件或包含函数顶部一样而类声明不会。
类声明除了语句到形式外还有表达式的形式。不过这种形式并不常用
let Persopn class { constructor() {} }
3.1 静态方法
在class体中把static关键字放在方法声明前面可以定义静态方法。静态方法是作为构造函数而非原型的属性定义的。
class Person {static hello() {console.log(hello word)}
}Person.hello(); // hello word
let p new Person();
p.hello(); // 报错p.hello is not a function
静态函数必须通过构造函数而非实例调用。
3.2 获取和设置方法
在class 体内可像对象字面量中一样定义获取方法和设置方法唯一的区别是类体内的方法后面不加逗号。
class Person {set age(val) {if (val 0) throw new TypeError(年龄不能小于0)this.age val}
}let person new Person();
person.age -1
console.log(person.age)
4 子类
ES6之前定义子类的方式是通过原型ES6则通过extends定义子类。
4.1 子类与原型
function Person() {console.log(Person的构造器)
}Person.prototype {constructor: Person,showType() {console.log(Person)}
}function Man() {console.log(Man的构造器)
}Man.prototype Object.create(Person.prototype)
let man new Man();
man.showType()
console.log(man.constructor)Man.prototype.constructor Man
console.log(man.constructor)只有在知道父类实现细节的前提下才可能这样定义子类健壮的子类化机制应该允许类调用父类的方法和构造函数在ES6之前js中没有简单的方法做到这些。
4.2 通过extends和super创建子类
class Person {constructor() {console.log(Person: new.target)}
}class Man extends Person {constructor() {super();console.log(this)console.log(Man)}
}class Woman extends Person {constructor() {super();console.log(Woman)}
}let man new Man();
let woman new Woman()注意事项
1使用extends关键字定义了一个类则该类的构造函数必须使用super()调用父类构造器。 2在通过super()调用父类构造器之前不能在构造器中使用this关键字。 3new.target引用的是被调用的构造函数。
在实际开发中并不建议创建很多子类建议通过“组合”的方式来替代继承。