Miya

重新认识面向对象:从ES5到ES6
什么是面向对象 面向对象的三大基本特征 封装:把抽象出来的属性和对方法组合在一起,且属性值被保护在内部,只有通过...
扫描右侧二维码阅读全文
06
2016/03

重新认识面向对象:从ES5到ES6

什么是面向对象

面向对象的三大基本特征

  1. 封装:把抽象出来的属性和对方法组合在一起,且属性值被保护在内部,只有通过特定的方法进行改变和读取称为封装
  2. 继承:可以让某个类型的对象获得另一个类型的对象的属性和方法称为继承
  3. 多态:同一操作作用于不同的对象产生不同的执行效果,称为多态

JavaScript的面向对象

JavaScript通过原型(Prototype)的方式来实现面向对象

基于类的面向对象和基于原型的面向对象的比较

基于类的面向对象

在基于类的面向对象中,是构建在类(class)实例(instance)上的
类定义了所有用于具有某个特征对象的属性,是抽象的事物
实例是类的实例化,是其中的一个成员

基于原型的面向对象

在基于原型的语言中,无论是构造函数(constructor)、实例(instance)和原型(prototype),本身就是对象
基于原型的语言具有所谓原型对象的概念,新对象可以从中获得原始的属性

JavaScript中的__proto__属性用于访问其原型对象。对象本身有__proto__属性指向原型对象,而最后都会指向Object这个构造函数

ES5中的面向对象

ES5中对象的创建

在ES5中创建对象有两种方式:

  1. 使用对象字面量:将对象使用声明变量的方式进行
  2. 使用构造函数:将对象使用函数的形式声明,当对构造函数使用new进行实例化时,会将其内部this指向绑定实例对象上

    当使用普通的方式调用构造函数时,this的指向是windows{}
    采用new方式生成实例化对象时,this则指向实例化本身

ES5中对象的继承

prototype的原型继承

  • 为什么要使用prototype?

对于每一个实例对象,其内部方法的函数体是一样的,方法的执行结构只根据实例对象决定,然而生成的每个实例都会生成一个内部方法占用内存,如果使用分别调用的方法,会占用过多内存造成性能问题

  • 如何使用prototype实现继承?

在对象中将构造函数的prototype指向对象的一个实例
如果替换了prototype对象,必须手动将prototype.constructor重新指向其构造函数

使用call和apply方法实现继承

优点:只要一行代码就可以实现继承
缺点:call和apply不能继承原型上的属性和方法

  • 使用call实现继承
    在子类构造函数中使用call方法,即可实现子类构造函数继承父类构造函数的全部属性和方法
    
    //父类构造函数
    function Student (name, age, subject) {
    this.name = name;
    this.age = age; 
    this.subject = subject;
    }

//子类构造函数
function Pupil(name, age, subject, school) {
//使用call实现继承
Student.call(this, name, age, subject);
this.school = school;
}

//实例化Pupil
let pupil2 = new Pupil('小辉', 8, '小学义务教育课程', '北大附小');

**注意:** call和apply只能继承本地属性和方法,不能继承原型上的属性和方法

//父类构造函数
function Student (name, age, subject) {
this.name = name;
this.age = age;
this.subject = subject;
}
//原型上挂载study方法
Student.prototype.study = function() {
console.log('我在学习' + this.subject);
}

//子类构造函数
function Pupil(name, age, subject, school) {
//使用call实现继承
Student.call(this, name, age, subject);
this.school = school;
}

let pupil2 = new Pupil('小辉', 8, '小学义务教育课程', '北大附小');

//报错
pupil2.study(); //Uncaught TypeError: pupil2.study is not a function


* **使用apply实现继承**
使用apply实现继承的方式和call一致,唯一的不同是[参数]^(Parameter)需要使用数组的方法

## ES6中的面向对象
ES6中提供了基于类class的语法,但class本质上是ES6提供的语法糖

### ES6中对象的创建
我们可以使用ES6的class来创建类,如同在Java等语言一致
class类中有constructor方法,这个为构造方法,而构造方法内的this关键字则代表实例对象
也就是说,在ES5中的构造函数,对应的则是ES6中class类的constructor方法

在ES6中定义类内部的方法时,不需要加function关键字直接定义函数即可;方法之间也不要用逗号分隔。类中的方法全部定义在原型原型上
### ES6中对象的继承
ES6中class可以通过extends关键字来实现继承
**注意:** 使用extends继承实现子类继承父类时,子类必须在constructor方法中首先调用super方法。这是因为子类继承于父类的this对象,不调用super方法则无法得到this对象,从而报错
最后修改:2018 年 09 月 12 日 09 : 21 PM

コメントする

Home
Change
Photo
About
Hide