1.类与实例
1.类的声明
1.构造函数声明
function Animal(name,age){
this.name = name;
this.age = 20;
}
//给构造函数的原型添加方法,在原型上添加可以进行数据共享、节省内存空间
Animal.prototype.say = function(){
console.log("我叫"+this.name+",我今年"+this.age+"岁了。")
}
2.ES6中的class声明
class Animal2{
//可以定义实例属性
sex = "母"
//定义静态属性
static hobby = "吃"
//构造器
constructor(name,age){
this.name = name;
this.age = age;
}
//相当于在原型对象上添加的方法
say(){
console.log("我叫"+this.name+",我今年"+this.age+"岁了。");
}
//静态方法
static like(){
console.log("我喜欢"+Animal2.hobby);
}
}
var animal2 = new Animal2("dog",20);
animal2.name;
animal2.say();
Animal2.hobby;
Animal2.like();
2.生成实例
var animal = new Animal("dog",20);
var animal2 = new Animal2("dog",20);
2.类与继承
实现继承的几种方式
类的继承的本质就是原型链
1.借助构造函数
缺点:只能继承父类的实例属性,不能继承其原型对象的方法和属性
//父类构造函数
function Parent(name){
this.name = name;
this.type = "Parent";
}
//父类添加公共方法
Parent.prototype.say = function(){
console.log("hello Parent.")
}
//子类构造函数
function Child(msg){
//借助构造函数实现继承,只能继承父类的实例属性,不能继承其原型对象的方法和属性
Parent.call(this,"child");
this.msg = msg;
}
2.借用原型链
缺点:修改了其原型中的引用类型的值,结果其他实例对象中的值也改变了
//父类构造函数
function Parent(name){
this.name = name;
this.type = [1,2,3,4,5,6];
}
//父类添加公共方法
Parent.prototype.say = function(){
console.log("hello Parent.")
}
//子类构造函数
function Child(msg){
this.msg = msg;
}
//借助原型链实现继承,Child的原型为父类的一个实例
Child.prototype = new Parent();
var child1 = new Child("hello");
var child2 = new Child("world");
//修改了其原型中的引用类型的值,结果其他实例对象中的值也改变了
child2.type.push(7);
3.使用组合方式实现继承
缺点:child.constructor === Parent,而不是Child,无法区分实例到底是由子类创建的还是父类创建的,而且不能修改子类的prototype.constructor,因为修改后父类的prototype.constructor也会修改,指向相同
//父类构造函数
function Parent(name){
this.name = name;
this.type = [1,2,3,4,5,6];
}
//父类添加公共方法
Parent.prototype.say = function(){
console.log("hello Parent.")
}
//子类构造函数
function Child(msg){
//1.借助构造函数实现继承,继承父类的实例属性和方法
Parent.call(this,"child");
this.msg = msg;
}
//2.借助原型链实现继承,Child的原型为父类的原型对象,即它们原型对象的引用相同
Child.prototype = Parent.prototype;
var child1 = new Child("hello");
var child2 = new Child("world");
//此时修改的只是child2的type属性,child1中的type属性没有改变,因为type属性为实例属性
child2.type.push(7);
//false
child1.__proto__.constructor === Child
//true
child1.__proto__.constructor === Parent
升级1:
//父类构造函数
function Parent(name){
this.name = name;
this.type = [1,2,3,4,5,6];
}
//父类添加公共方法
Parent.prototype.say = function(){
console.log("hello Parent.")
}
//子类构造函数
function Child(msg){
//1.借助构造函数实现继承,继承父类的实例属性和方法
Parent.call(this,"child");
this.msg = msg;
}
//2.借助原型链实现继承,Child的原型为一个对象,该对象的原型为父类的原型对象
Child.prototype = Object.create(Parent.prototype);
//赋值原型的constructor为本身
Child.prototype.constructor = Child
var child1 = new Child("hello");
var child2 = new Child("world");
//此时修改的只是child2的type属性,child1中的type属性没有改变,因为type属性为实例属性
child2.type.push(7);
//true
child1.__proto__.constructor === Child
//false
child1.__proto__.constructor === Parent
4.ES6中的继承
class Animal{
//可以定义实例属性
sex = "母"
//定义静态属性
static hobby = "吃"
//构造器
constructor(name){
this.name = name;
}
//相当于在原型对象上添加的方法
say(){
console.log("我叫"+this.name+",我今年"+this.age+"岁了。");
}
//静态方法
static like(){
console.log("我喜欢"+Animal.hobby);
}
}
//子类
class Dog extends Animal{
constructor(name,age){
//必须先调用super(name);否则拿不到this
//super作为函数使用,代表调用父类的constructor,等价于Animal.prototype.construcor.call(this,name);返回的结果为Dog的实例
super(name);
this.age = age;
//super作为对象使用,设置的属性就是该dog实例的属性
super.name = "dog";
//super作为对象使用,如果调用的方法是普通方法,则super代指父类的原型对象
//等价于Animal.prototype.say.call(this)
super.say();
}
static myLike(){
//super作为对象使用,如果调用的方法是静态方法,则super代指父类
//等价于Animal.like.call(this)
super.like();
}
}
var dog = new Dog("dog",20);
dog.name;
dog.say();
Dog.hobby;
Dog.myLike();