JavaScript 面向对象编程实现

原创 2017年01月03日 18:08:52

JavaScript 面向对象编程实现

本文主要讲述js面向对象的实现方式(继承)

面向对象本来就是把某些问题(逻辑),用对象的方式描述,使得业务逻辑能更加清晰,提高维护性,降低实现复杂度。

面向对象的三大特征:封装,多态,继承。(JavaScript 是没有多态的特性的)。JavaScript的面向对象使用prototype实现的,与其他面向对象语言非常不一样。
实现JavaScript的继承,

属性继承

call() 方法

function subClass(){
    this.food = 'apple'
    superClass.call(this);
    console.log(this.action+ ' a ' +this.food );
}

function superClass(){
    this.action = 'eat'
}

var  shili = new subClass();// eat a apple

apply() 方法

function subClass(){
    this.food = 'apple'
    superClass.apply(this);
    console.log(this.action+ ' a ' +this.food );
}

function superClass(){
    this.action = 'eat'
}

var  shili = new subClass();// eat a apple

这种方法相当于调用superClass 的构造器,并且使superClass this 指向 subClass 的this,这样subClass内部属性就会有 superClass的属性。

这种方式继承来的方法,是静态的,只要subClass 实例化后,父类的改动是不会影响子类的。

原型继承

ES5原型对象关系图

这里写图片描述

原型链

prototype 是JavaScript 独特的继承方法,用另一种方式诠释面向对象。
那么他有什么特别之处呢?

  1. java语言特性没有多态的概念。
  2. 继承的原型是动态的,共享的。
  3. 没有私有属性

下面是程序例子

function superClass(){
    this.say = function(){
        console.log('i m subclass');
    }
}

function subClass(){
    this.say = function(){
        console.log('i m subclass');
    }
}

subClass.prototype = new superClass();
subClass.prototype.constructor = subClass;

这是非常常用的方法,对于javascript 来说,没有继承的标准,所以继承的方式可以说是百花齐放,我个人是觉得 prototype的写都不太优雅,所以对于我来说,es5的继承方式都是大同小异的,实际上也是这样的。

混合方式

在某些时候,我们需要传入参数到父类 ,这种需求在 call /apply 上很轻松实现到,但用原型链就没法实现了,怎么办呢? 一起用就好了!
(W3school 中的例子)

function ClassA(sColor) {
this.color = sColor;
}

ClassA.prototype.sayColor = function () {
    alert(this.color);
};

function ClassB(sColor, sName) {
    ClassA.call(this, sColor);
    this.name = sName;
}

ClassB.prototype = new ClassA();

ClassB.prototype.sayName = function () {
    alert(this.name);
}; 

var objA = new ClassA("blue");
var objB = new ClassB("red", "John");
objA.sayColor();    //输出 "blue"
objB.sayColor();    //输出 "red"
objB.sayName(); //输出 "John"

ES6 继承

虽然说ES6只是语法糖,但是ES6确实拥有一些ES5不一样的东西,虽然ES5同样能实现。

ES6的继承本质上是没有离开原型继承的。但是在extends关键字 在处理 子父类的时候会跟ES6会有不一样,下图是关于ES6 父子类之间的关系图,读者可以与ES5的原型链继承关系图对比一下。

这里写图片描述

我们在关系图中能发现,2图只有 父类与子类之间关系发生了变化,子类的__proto__ 指向了父类,这样给我们带了一个小特性:子类可以继承父类的静态方法/属性,这种小特性在封装组件的过程是非常有用的,类的概念会更加清晰(感觉就很打脸,当初为何要搞原型呢?)

这里有一段 Babel 翻译ES6的代码:

ES6 (语法也就是这个样子)

class Father{
    constructor(name, age){
        this.name = name;
        this.age = age;
    }

    show(){
        console.log(`我叫:${this.name}, 今年${this.age}岁`);
    }
};
class Son extends Father{};

let son = new Son('金角大王', 200);
son.show();//return 我叫:金角大王, 今年200岁

翻译过程:

"use strict";

var _createClass = function () {
    function defineProperties(target, props) {
        for (var i = 0; i < props.length; i++) {
            var descriptor = props[i];
            descriptor.enumerable = descriptor.enumerable || false;
            descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true;
            Object.defineProperty(target, descriptor.key, descriptor);
        }
    }
    return function (Constructor, protoProps, staticProps) {
        if (protoProps) defineProperties(Constructor.prototype, protoProps);
        if (staticProps) defineProperties(Constructor, staticProps); return Constructor;
    };
}();

function _possibleConstructorReturn(self, call) {
    if (!self) {
        throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
    }
    return call && (typeof call === "object" || typeof call === "function") ? call : self;
}

function _inherits(subClass, superClass) {
    if (typeof superClass !== "function" && superClass !== null) {
        throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
    }
    subClass.prototype = Object.create(
        superClass && superClass.prototype,
        {
            constructor: { value: subClass, enumerable: false, writable: true, configurable: true }
        }
        );
    if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }


var Father = function () {
    function Father(name, age) {
        _classCallCheck(this, Father);

        this.name = name;
        this.age = age;
    }

    _createClass(Father, [{
        key: "show",
        value: function show() {
            console.log("我叫:" + this.name + ", 今年" + this.age + "岁");
        }
    }]);

    return Father;
}();

;

var Son = function (_Father) {
    _inherits(Son, _Father);

    function Son() {
        _classCallCheck(this, Son);

        return _possibleConstructorReturn(this, Object.getPrototypeOf(Son).apply(this, arguments));
    }

    return Son;
}(Father);

参考资料:
W3school
阮一峰ECMAScript入门;
《JavaScript权威指南》 作者:Flanagan
某文章(记得看评论区,评论区有指出错误)

版权声明:本文为博主原创文章,未经博主允许不得转载。

JavaScript实现计算器功能

代码如下: New Document var flag = false; function display(val){ var display = document.getE...
  • suwu150
  • suwu150
  • 2016年11月07日 21:23
  • 899

javascript实现分页效果

一般的页面我们实现分页效果都是用跳转的形式,但是有些需求需要我们在不跳转页面的同时完成分页效果,简单的一个实现例子:window.onload = function(){ page...
  • yilanyoumeng3
  • yilanyoumeng3
  • 2015年06月18日 16:24
  • 1822

用javascript实现简单计算器

这是一个简单计算器的实现。可以实现简单的加,减,乘,除功能,用户按下“←”按钮,删除当前算术表达式最后一个字符,并更新显示,用户按下“CE”按钮,清除当前算术表达式,如果算术表达式非法,弹出警告框提醒...
  • XHF901
  • XHF901
  • 2016年12月09日 15:49
  • 328

JavaScript实现简单日历

JavaScr
  • u011043843
  • u011043843
  • 2014年06月08日 23:32
  • 1656

JavaScript:利用JavaScript实现的功能、算法和奇淫技巧(持续更新)

1、JavaScript:输入日期获得从该日期开始的一个月时间function getNextMonth(time) { var arr = time.split(/-|\//...
  • DOCALLEN
  • DOCALLEN
  • 2017年05月02日 17:08
  • 766

javascript实现选项卡切换效果

javascript实现选项卡切换效果
  • u014610047
  • u014610047
  • 2016年02月19日 14:00
  • 1228

基于javascript的简单数据可视化:DVisual

基于html5和javascript的简单数据图表绘制,很方便地就可以得到精美的图像。 最近看了不少数据可视化的书,所以也就顺理成章想做点东西,同时准备把『数据可视化套件开发』这个作为毕业设计搞一搞,...
  • Dark_Scope
  • Dark_Scope
  • 2015年02月01日 11:11
  • 6903

JavaScript的组成和实现

JavaScript 的核心ECMAScript 描述了该语言的语法和基本对象; DOM 描述了处理网页内容的方法和接口; BOM 描述了与浏览器进行交互的方法和接口。    ECMAScri...
  • jbjwpzyl3611421
  • jbjwpzyl3611421
  • 2014年02月18日 17:06
  • 1076

Javascript中的几种继承方式比较

开篇 从’严格’意义上说,javascript并不是一门真正的面向对象语言。这种说法原因一般都是觉得javascript作为一门弱类型语言与类似java或c#之类的强型语言的继承方式有很大的区别,...
  • kkkkkxiaofei
  • kkkkkxiaofei
  • 2015年06月12日 17:32
  • 10678

利用javascript实现简单动画效果。

利用javascript的setTimeout()函数可以实现简单的动画效果。setTimeout()函数有两个参数,第一个参数是一个字符串,其内容是将要执行的哪个函数的名字;第二个参数是一个数值,它...
  • qq_32600929
  • qq_32600929
  • 2016年11月03日 11:35
  • 1299
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:JavaScript 面向对象编程实现
举报原因:
原因补充:

(最多只允许输入30个字)