一、定义“类” ——构造函数
我们知道,JavaScript中没有类的概念,我们只是通过函数来模仿类的行为,我们将它称之为
构造函数
构造函数
分两类,原生构造函数和自定义构造函数。原生构造函数
像Array、Object,是执行环境自动提供的;自定义构造函数
是我们自己来创建的
当你想用相同的属性和方法创建多个相似的对象时,构造函数是非常有用的。
定义构造函数的方法:
function Animal(name){
//此判断是使用时缺省new关键词时的安全策略
if(!(this instanceof Animal)){
return new Animal(name);
}
this.name = name;
}
Animal.prototype = {
eat: function(){
console.log('I am eating');
}
}
var dog = new Animal();
dog.eat(); // I am eating
在调用new创造实例时,做了下面几件事:
构造函数中的this指向当前出发执行的对象,即dog,所以在dog本身添加了属性name
dog的
__proto__
指向Animal的prototype
,对dog.__proto__
中属性的修改会引起Animal中prototype
的变化,从而使得所有由Animal创造的实例__proto__
中的属性改变(引用类型,全都指向同一地址)dog的
constructor
属性指向Animal本身,因为dog的constructor
指向Animal本身,所以我们可以通过instanceof来判断dog是否为Animal的实例,但是constructor可以被改写,所以通过instanceof来判断不一定准确
二、继承
在JavaScript中一切都是对象,当我们谈到继承,其实是对象从对象中的继承,而不是类从类中的继承
很多时候我们在创建多个具有相同属性的实例时,可能有几个具有自己特有的属性,所以我们需要先继承公共构造函数中的属性,然后改写自己特有的属性
继承写法:
function Animal(name){
if(!(this instanceof Animal)){
return new Animal(name);
}
this.name = name;
}
Animal.prototype = {
eat: function(){
console.log('I am eating');
}
}
function Mammalia(name, age){
this.name = name;
this.age = age;
}
Mammalia.prototype = new Animal();
var dog = new Mammalia('hashiqi', 5);
最后生成的原型链如图:
三、ES6中的class
class
一直是 JS 的关键字(保留字),但是一直没有正式使用,在ES6中终于使用到了它,通过class来定义构造函数,从语法上更加符合面向对象的写法
对目录一中代码的改写:
class Animal {
constructor(name){
this.name = name;
}
eat(){
console.log('I am eating');
}
}
var dog = new Animal();
dog.eat(); // I am eating
对目录二继承代码的改写:
class Animal {
constructor(name){
this.name = name;
}
eat(){
console.log('I am eating');
}
}
class Mammalia extends Animal {
constructor(name, age){
super(name);
this.name = name;
this.age = age;
}
}
var dog = new Mammalia('hashiqi', 5);
注意:
子类
的constructor一定要执行super()
,以调用父类
的constructor- 继承的关键词是
extends
,不要忘记s class
是ES6提供的一种语法糖
,其内部实现原理还是一样的