在面向对象编程中,类(class)是对象(object)的模板,定义了同一组对象(又称”实例”)共有的属性和方法。
Javascript语言不支持”类”,但是可以构造函数的方法,模拟出”类”。
- 构造函数:
构造函数就是一个普通的函数,但内部使用了this变量,对构造函数使用 new 运算符就能声称事例,并且this变量会帮定在实例对象上。
function Cat(name,color){
this.name = name;
this.color = color;
}
//每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。
//共有属性和方法可以直接定义在prototype上,指向同一个内存地址
Cat.prototype.type = "猫科动物";
Cat.prototype.eat = function(){
alert("小猫爱吃鱼");
}
var cat1 = new Cat("小白","white");
var cat2 = new Cat("小黑","black");
alert(cat1.eat == cat2.eat); //true
- Prototype模式的验证方法
- isPrototypeOf() : 用于判断某个prototype对象和某个实例之间的关系
alert(Cat.isPrototypeOf(cat1)) //true
alert(Cat.isPrototypeOf(cat2)) //true
-
- hasOwnPrototype :每个实例化对象都有一个hasOwnPrototype()方法,用于判断某个属性是实例对象属性还是pototype对象属性
alert(cat1.hasOwnPrototype("name")) //true
alert(cat1.hasOwnPrototype("type")) //false
-
- in运算符
用于查看某个实例是否为某个对象的属性,不管是实例对象属性还是原型对象的属性
- in运算符
alert("name" in cat1) //true
alert("type" in cat1) //true
运算符还可以用来遍历某个对象的所有属性
for(var prop in cat1) { alert("cat1["+prop+"]="+cat1[prop]); }
- 利用空对象作为中介的构造函数的继承
function Animal(){ }
Animal.prototype.species = "动物";
function Cat(name,color){
this.name = name;
this.color = color;
}
//使猫继承于动物 封装成inherits()
function inherits(Child, Parent) {
var F = function () {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
}
//使用该方法
inherits(Cat,Animal);
var cat1 = new Cat("大白","whiteMax");
alert(cat1.species) //动物
class继承
- 从ES6开始关键字class被引入javascript中,目的:让定义类更简单
- 比较:JavaScript的对象模型是基于原型实现的,特点是简单,缺点是理解起来比传统的类-实例模型要困难,最大的缺点是继承的实现需要编写大量代码,并且需要正确实现原型链。
class类定义
class Cat{
constructor(name,color){
this.name = name;
this.color = color;
};
eat(){
alert("小猫爱吃鱼")
}
}
//实例化
var cat1 = new Cat("小白","white");
var cat2 = new Cat("小黑","black");
console.log(cat1.eat === cat2.eat) //true
console.log(cat1.name === cat2.name) //false
console.log(Cat.isPrototypeOf(cat1)) //false //不是通过原型对象创建的
- class继承
class Animal{
constructor(name){
this.name = name;
this.species = "动物"
}
}
class Cat extends Animal{
constructor(name,color){
super(name); //继承父类的constructor(name)
this.color = color;
}
hello(){
return "Hello, "+this.name +"!";
}
}
var cat1 = new Cat("小白","white");
var cat2 = new Cat("小黑","black");
console.log(new Cat('x') instanceof Animal) //true
console.log(cat1.species) //动物 --> 证明Cat继承Animal类
console.log(cat1.hello() === cat2.hello()); //false
-
extends则表示原型链对象来自Animal。子类的构造函数可能会与父类不太相同,例如,Cat需要name和color两个参数,并且需要通过super(name)来调用父类的构造函数,否则父类的name属性无法正常初始化。
Cat已经自动获得了父类Animal的species属性,我们又在子类中定义了新的hello()方法。
ES6引入的class和原有的JavaScript原型继承实际上它们没有任何区别,class的作用就是让JavaScript引擎去实现原来需要我们自己编写的原型链代码。简而言之,用class的好处就是极大地简化了原型链代码。
需要一个工具把class代码转换为传统的prototype代码,可以试试Babel这个工具。
- 参考链接