深入理解js中实现继承的原理和方法

2019-01-29  本文已影响11人  龙旗飘扬的舰队

原型对象继承

//对象继承
var person = {
  name:"gs",
  age:19
}
console.log(person.prototype === undefined );
function Student(){}
Student.prototype = person;//原型属性经由对象实例访问
console.log(new Student());
//构造函数继承
function Person(){
  this.name = "gs";
  this.age = 19;
}
function Student(){
  this.name = "zk"
}
Student.prototype = new Person();//原型属性经由对象实例访问
var zk = new Student();
console.log(zk);

Object是顶层对象

定义在 Object.prototype 上的方法

valueOf

toString

let obj = { name:"gs" };
console.log(obj+111)//;[object Object]111
console.log(obj.toString());//[object Object]
console.log(obj.valueOf());//{ "name": "gs" }

最好不要去修改 Object.prototype

最简单的一个对象继承

var student1 = {
  name:"gs"
}
var student2 = Object.create(Object.prototype,{
  name:{
    configurable:true,
    enumerable:true,
    value:"gs",
    writable:true,
  }
})

实现一个基本的对象继承

//对象继承
var person = {
  name:"gs",
  age:19
}
console.log(person.prototype === undefined );
function Student(){}
Student.prototype = person;//原型属性经由对象实例访问
console.log(new Student());

实现一个稍复杂的构造函数继承

function Person(school,name,age){
  this.school = "beijing univercity";
  this.name = name;
  this.age = age;
}
Person.prototype.sayName = function(){
  console.log(this.name);
}
Person.prototype.sayAge = function(){
  console.log(this.age);
}

function Student(name,age){
  this.name = name;
  this.age = age;
}
Student.prototype = new Person();
var gs = new Student("gs",19);
console.log(gs.constructor);//Person
Student.prototype.constructor = Student;//注意!要重写构造器属性,否则将被设为父类的值
console.log(gs.constructor);//Student
Student.prototype.sayName = function(){
  console.log("student is "+this.name);
}
console.log(gs.sayName());
console.log(gs.sayAge());

实现一个伪类继承(构造函数窃取)

function Person(school,name,age){
  this.school = "beijing univercity";
  this.name = name;
  this.age = age;
}
Person.prototype.sayName = function(){
  console.log(this.name);
}
Person.prototype.sayAge = function(){
  console.log(this.age);
}

function Teacher(school){
  Person.call(this,...arguments);//因为this指向Teacher,所以constructor属性仍将是Teacher
  this.school = school;//注意,新的属性,应置于继承发生之后,以做覆盖
}
var zk = new Teacher("haver","zk",23);
console.log(zk.constructor);//constructor属性正确,为Teacher
console.log(zk.sayName === undefined);//true,但是,没有继承原型方法和属性
Teacher.prototype = new Person();
var zk_2 = new Teacher("haver","zk_2",23);//没有继承原型方法
console.log(zk_2.sayName());//拿到方法了
console.log(zk_2.constructor);//Person。不是吧,constructor属性又不对了
Teacher.prototype.constructor = Teacher;
console.log(zk_2.constructor);//Teacher。使用call方式继承属性,仍然需要用prototype方式继承方法,同时还要设置constructor

父类方法被子类覆盖,如何仍然可以调用?

function Person(name,age){
  this.name = name;
  this.age = age;
}
Person.prototype.sayName = function(){
  console.log("father method " + this.name);
}
Person.prototype.sayAge = function(){
  console.log(this.age);
}

function Student(){
  Person.call(this,...arguments);
}
Student.prototype = Object.create(Person.prototype,{
  constructor:{
    configurable:true,
    enumerable:true,
    value:Student,
    writable:true,
  }
})
Student.prototype.sayName = function(){
  console.log("child method");
}
Student.prototype.sayName_1 = function(){
  Person.prototype.sayName.call(this);//这是唯一的访问父类的方法
}
var gs = new Student("gs",20);
console.log(gs);

console.log(gs.sayName_1());

创建一个没有原型对象的对象

var obj = Object.create(null);
console.log(obj.prototype === undefined);
console.log( valueOf in obj);
console.log( toString in obj);
上一篇 下一篇

猜你喜欢

热点阅读