继承可以帮助我们将重复的代码和逻辑抽取到父类中,子类只需要直接继承过来使用即可。
在真正实现继承之前,我们先来理解一个非常重要的概念:原型链。
从一个对象上获取属性,如果在当前对象中没有获取到就会去它的原型上面获取
原型链最顶层的原型对象就是Object
的原型对象
原型链的尽头 [Object: null prototype] {}
了解完原型链,就可以利用原型链来实现继承了
// 父类: 公共属性和方法
function Person() {
this.name = "蜘蛛侠"
this.friends = []
}
Person.prototype.eating = function() {
console.log(this.name + " eating~")
}
// 子类: 特有属性和方法
function Hero() {
this.age= 111
}
var p = new Person()
Hero.prototype = p
Hero.prototype.killing = function() {
console.log(this.name + "正在大开杀戒")
}
// name/age
var hero = new Hero()
// console.log(hero.name)
// hero.eating()
// hero.killing ()
// 原型链实现继承的弊端:
// 1.第一个弊端: 打印hero对象, 继承的属性是看不到的
console.log(hero)
// 2.第二个弊端: 创建出来两个hero的对象
var hero1 = new Hero()
var hero2 = new Hero()
// 直接修改对象上的属性, 是给本对象添加了一个新属性
hero1.name = "金刚狼"
console.log(hero2)
// 获取引用, 修改引用中的值, 会相互影响
hero1.friends.push("蝙蝠侠")
console.log(hero1.friends)
console.log(hero2.friends)
// 3.第三个弊端: 在前面实现类的过程中都没有传递参数
var stu3 = new Hero("超人", 112)
constructor stealing
(有很多名称: 借用构造函steal
是偷窃、剽窃的意思,但是这里可以翻译成借用;apply()
和call()
方法也可以在新创建的对象上执行构造函数;// 父类: 公共属性和方法
function Person(name, friends) {
// this = stu
this.name = name
this.friends = friends
}
Person.prototype.eating = function() {
console.log(this.name + " eating~")
}
// 子类: 特有属性和方法
function Hero(name, friends, age) {
Person.call(this, name, friends)
this.age= 18
}
var p= new Person('普通人',[],18)
Hero.prototype = p
Hero.prototype.kill = function() {
console.log(this.name + '正在大开杀戒')
}
var spiderMan = new Hero("蜘蛛侠",['玛丽简'],18)
//解决原型链继承的弊端
//1、打印spiderMan对象就可以看到继承的属性
console.log(spiderMan)
//2、创建出两个对象
hero1 = new Hero('钢铁侠',['小辣椒'],35)
hero2 = new Hero('蝙蝠侠',['小丑'],35)
/// 获取引用, 修改引用中的值不会相互影响
hero1.friends.push("奥创")
console.log(hero2.friends)
person
本身的),另一份在子类对应的原型对象中(也就是person.__proto__
里面);Prototypal Inheritance in JavaScript
(在JS中使用原型式继承)JavaScript
想实现继承的目的:重复利用另外一个对象的属性和方法.var obj = {
name: "死侍",
age: 37
}
var info = Object.create(obj)
// 原型式继承函数
function createObject2(o) {
function Fn() {}
Fn.prototype = o
var newObj = new Fn()
return newObj
}
var info = createObject2(obj)
console.log(info.name)
console.log(info.__proto__)
var personObj = {
running: function() {
console.log("running")
}
}
function createStudent(name) {
var stu = Object.create(personObj)
stu.name = name
stu.studying = function() {
console.log("studying~")
}
return stu
}
var stuObj = createStudent("死侍")
var stuObj1 = createStudent("金刚狼")
var stuObj2 = createStudent("小丑")
function createObject(o) {
function Fn() {}
Fn.prototype = o
return new Fn()
}
function inheritPrototype(SubType, SuperType) {
SubType.prototype = Object.create(SuperType.prototype)
Object.defineProperty(SubType.prototype, "constructor", {
enumerable: false,
configurable: true,
writable: true,
value: SubType
})
}
function Person(name, age, friends) {
this.name = name
this.age = age
this.friends = friends
}
Person.prototype.running = function() {
console.log("running~")
}
Person.prototype.eating = function() {
console.log("eating~")
}
function Student(name, age, friends, sno, score) {
Person.call(this, name, age, friends)
this.sno = sno
this.score = score
}
inheritPrototype(Student, Person)
Student.prototype.studying = function() {
console.log("studying~")
}
var stu = new Student("why", 18, ["kobe"], 111, 100)
console.log(stu)
stu.studying()
stu.running()
stu.eating()
console.log(stu.constructor.name)