Javascript是一门灵活的语言,她本身并不支持面向对象,也没有定义类的关键字class和实现继承的extends这些;
但是Javascript还是可以灵活变通,模拟出"类“”的;
一、js中定义类:
1.构造函数法:
function Person(){
this.name = '张三'; //实例上的属性
this.age = 18;
this.run = function(){ //实例方法,要调用实例方法必须new Person()
console.log(this.name+'在跑步!')
}
}
Person.prototype.sex = '男'; //原型链上的属性
Person.prototype.work = function (){ //原型链上的方法,也叫静态方法
console.log(`${this.name}在工作!`)
}
2. Object.create()法
var Person = {
name: '张三', //实例上的属性
age: 18,
run: function(){ //实例方法,要调用实例方法必须Object.create(Person);
console.log(this.name+'在跑步!')
}
}
var p = Object.create(Person);
console.log(p.name); // 张三
p.run(); // 张三在跑步
2. 工厂方法
function person(name, age){
var p = new Object();
p.name = name;
p.age = age;
p.run = function(){
console.log(`${this.name}今年${this.age}岁了`)
};
return p;
}
var per = person('张三', 15);
per.run()
var per1 = person('李四', 18);
per1.run()
二、类的继承
1.对象冒充继承法
function Person(){
this.name = '张三'; //实例上的属性
this.age = 18;
this.run = function(){ //实例方法,要调用实例方法必须new Person()
console.log(this.name+'在跑步!')
}
}
Person.prototype.sex = '男'; //原型链上的属性
Person.prototype.work = function (){ //原型链上的方法,也叫静态方法
console.log(`${this.name}在工作!`)
}
//对象冒充继承,可以继承构造函数里面的属性和方法,但不能继承原型链上的属性和方法
function Web(){
Person.call(this); //对象冒充继承
}
var w = new Web();
console.log(w)
console.log(w.name)
// console.log(w.sex) => undefined
注意: 对象冒充继承,可以继承构造函数里面的属性和方法,但不能继承原型链上的属性和方法
2.原型链实现继承
function Person(){
this.name = '张三'; //实例上的属性
this.age = 18;
this.run = function(){ //实例方法,要调用实例方法必须new Person()
console.log(this.name+'在跑步!')
}
}
Person.prototype.sex = '男'; //原型链上的属性
Person.prototype.work = function (){ //原型链上的方法,也叫静态方法
console.log(`${this.name}在工作!`)
}
//原型链实现继承,即可以继承构造函数里面的属性和方法,也可以继承原型链上的属性和方法
function Web(){ }
// 1、
Web.prototype = new Person(); //原型链继承
var w = new Web();
console.log(w.name)
// 2、
Web.prototype = Person.prototype; //原型链继承
var w = new Web('李四');
console.log(w.name) => undefined
console.log(w.sex)
//*** 原型链实现继承存在一个的问题? 实例化子类的时候无法给父类传参
//*** 请看第三种方法
注意: 原型链实现继承,即可以继承构造函数里面的属性和方法,也可以继承原型链上的属性和方法,但是原型链实现继承存在一个的问题? 实例化子类的时候无法给父类传参
3.原型链+构造函数 组合继承法
//原型链+构造函数的组合模式继承
function Person(name, age){
this.name = '钱六'; //实例上的属性
this.age = 7;
this.run = function(){ //实例方法,要调用实例方法必须new Person()
console.log(this.name+'在run!')
}
}
Person.prototype.sex = '男6'; //原型链上的属性
Person.prototype.study = function (){ //原型链上的方法,也叫静态方法
console.log(`${this.name}在study!`)
}
function Web(name, age){
Person.call(this, name, age)
}
Web.prototype = new Person();
var w = new Web('赵四', 600);
console.log(w)
console.log(w.name)
console.log(w.age)
w.study();
4. 寄生式继承 (Object.create)
// 寄生式继承 (Object.create)
let Parent = {
name: 'parent',
getName: function() {
return this.name;
}
}
function Child(parent) {
let obj = Object.create(parent);
console.log(obj)
obj.setName = function (name) {
this.name = name;
return this.name
}
return obj
}
let c = Child(Parent)
console.log(c.setName('小明'))
console.log('child -->', c.getName())
注意: 寄生式继承不能实例化,也没有用到原型。
5. 寄生式组合式继承
function Parent() {
this.name = '张三';
this.getName = function () {
return this.name
};
this.list = [1,2,3]
}
Parent.prototype.study = function () {
return `${this.name}在study!`
}
function Child() {
Parent.call(this)
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child; //手动修改 constructor 的指向
const c= new Child();
console.log(c)
console.log(c.list)
console.log(c.getName())
console.log(c.study())