JavaScript面向对象 ~ 原型和继承(1)

通过面试的挫折以后,继续深刻学习~~面试

一、原型概念的提出

传统的构造函数对象包含方法时,在构造函数建立时,就会将全部内容从新建立一次,致使数据的重复,代码的冗余,以下所示:

function Person(name, age) {
  this.name = name;
  this.age = age;
  this.sayHello = function () {
    console.log("Hello");
  }
}
var p1 = new Person();
var p2 = new Person();
p1.sayHello === p2.sayHello // 结果为false,由于p1,和p2的sayHello虽结构同样,但倒是两个不一样的对象

改良1:将方法提取到外面框架

function sayHello(){
  console.log("Hello");
}
function Person(name, age) {
  this.name = name;
  this.age = age;
  this.sayHello = sayHello;
}
var p1 = new Person();
var p2 = new Person();
p1.sayHello === p2.sayHello // 结果为true,但当代码量不断增长,自定义的函数愈来愈多时,可能会和框架中的函数发生命名冲突,也不利于代码的维护

改良2:将方法放到构造函数中,且避免命名冲突,原型概念出现函数

function Person(name, age) {
  this.name = name;
  this.age = age;
}
Person.prototype.sayHello = function (){
   console.log("Hello");
}
var p1 = new Person();
var p2 = new Person();
p1.sayHello === p2.sayHello // 结果为true

构造函数一旦被建立,就会有一个原型属性,也是个对象,能够往里面添加成员,每一个由构造函数建立出来的对象都会默认链接到原型属性上去。学习

当js引擎查找对象属性时,会先查找对象上是否具备该属性,若是没有,就会去原型属性上去查找。this

因此,什么是原型?原型是可以实现继承的,当构造函数被定义的时候,原型也就被建立出来,它能够存储属性和方法,既是一个属性也是一个对象。当构造函数建立的实例对象须要访问某个方法或属性,而这个对象又没有该方法或属性的时候,它会去原型上面去查找。也就是实例对象访问原型对象的属性或调用原型对象的方法,说的通俗一点也就是把别的对象的方法或属性拿过来本身用,就是继承,因此咱们也能够说对象继承自其原型。prototype

引入:属性查找机制:对象在访问属性或方法时,首先在当前对象查找,若是该对象有该属性或方法,则中止查找,若是没有,则去原型中查找,若是原型没有,则去原型的原型中查找,直到原型的顶部,若是仍是没有,则返回undefined(属性)或 xxx is not a function(方法)调试

二、一些相关概念

① 面向对象的相关概念

  • 类class:在js中就是构造函数
  • 实例(instance)与对象(object)
    实例是指某个构造函数建立出来的对象,咱们称之为xxx构造函数的实例;
  • 键值对与属性和方法
    在js中,键值对的集合称之为对象
    若是数据是值,该键值对为属性prototype
    若是数据是函数,该键值对为方法method
  • 父类与子类
    js中没有class的概念,由C++引伸过来,父类又称基类,子类又称派生类
    js中称为父对象、子对象

② 原型的相关概念

  • prototype针对构造函数,称为“原型属性”
  • prototype针对构造函数建立出来的对象,称为“原型对象”
  • 原型属性与原型对象的关系:
    !!构造函数的原型属性和构造函数建立出来的对象的原型对象,是一个东西
    !!构造函数的原型属性所指向的对象,与构造函数建立出来的对象(实例对象),这是两个不一样的对象(快绕晕了)

三、对象继承自其原型

构造函数建立出来的对象(实例对象)继承构造函数的原型属性和原型对象code

四、原型的使用

  • 利用对象的动态特性:在原来的对象上添加成员
    构造函数.prototype.xxx = ccc;
  • 直接替换:从新建立一个对象
    构造函数.prototype = {};

五、__proto__

经过 proto 容许实例对象直接访问原型,一般用于在调试中查看原型的成员(实例对象不容许修改原型)对象

六、原型的结构

有一个默认属性:constructor => 构造器,表示该原型是与什么构造函数联系起来的
∴ 构造函数经过 prototype 的属性访问原型,原型能够经过 constructor 访问构造函数继承

七、继承

  • 简单继承:将别的对象的方法或属性直接拿过来,加到本身身上,因而我就有了该方法或属性。=> 简单粗暴,层次清晰
  • 利用原型继承:不须要添加成员,只要原型具备,我便有了。=> 提升复用性
  • 混合式继承:将方法或属性利用混入的方法,加到构造函数原型中,实例对象即有了指定的方法或属性。

八、静态成员和实例成员的概念

该概念由其余面向对象的语言引入。

  • 静态成员表示的是静态方法和静态属性,由构造函数提供。
  • 实例成员表示的是实例方法和实例属性,由构造函数建立的对象,也就是实例对象提供。

九、小结

  • 什么是原型?
  • 如何使用原型?
  • 什么是原型继承? => 实例对象默认链接到原型中,能够继承原型的方法和属性,也能够本身给原型赋值
  • 如何实现? => 混合式继承
相关文章
相关标签/搜索