JavaScript——ES5和ES6面向对象编程实现继承

ES5实现继承

严格来说,ES5中没有类和继承的概念,但为了方便理解面向对象编程,姑且认为构造函数就是类,本身是一个函数。ES5实现继承有很多种方式,具体可查看《javascript高级程序设计》这本书,网上也有很多关于其他继承实现的具体介绍。这里我只列举了一种最优方式。

如果对this的理解不够深入,可以参考我的另外一篇博客JavaScript——this的理解和call、apply、bind的使用,希望对大家有所帮助!

function Father(opt) {
    this.name = opt.name;
    this.age = opt.age;
    this.height = opt.height;
}
Father.prototype = {
    constructor: Father,
    say: (value) {
        alertvalue)
    }
}

function Child(opt) {
    Father.call(opt); //实现父亲构造函数中属性的继承
}

inherits(Child, Father);
Child.prototype.eat = function() {} //为子类添加私有方法
//实现父亲原型的继承
function inherits(Child, Father) {
    var C= function () {};
    C.prototype = Father.prototype;
    Child.prototype = new C();
    Child.prototype.constructor = Child;
}

ES6实现继承

ES6新增了一个class关键字创建类,可通过extends和super关键字实现类的继承。

class Father {
    constructor(opt) {
        this.name = opt.name;
        this.age = opt.age;
        this.height = opt.height;
    }  //注意:这里不能加任何符号,逗号和分号也都不行
    say (value) {
        alertvalue)
    }
}
class Child extends Father {
    constructor(opt) {
        super(opt) //实现继承,注意,super必须写在第一行, 否则直接写this会报错
        this.sex = opt.sex;
    }
    eat() { //子类的私有方法

    }
}

由上面可以看出,ES6实现继承要方便多了

ES5和ES6实现继承的不同之处

下面是我总结的以上两种方式实现面向对象继承的不同之处:

  • ES5中的类本身是一个函数,可以当做函数调用,也可以通过new关键字创建实例对象;而通过class创建的类,只能通过new关键字创建类的实例对象。
  • 添加静态方法的方式不同,ES5直接通过 Father.fn = function(){} ;ES6通过static关键字添加静态方法
class Father {
    constructor(opt) {
        this.name = opt.name;
        this.age = opt.age;
        this.height = opt.height;
    } 
    static sleep () {

    }
}
  • ES6中类的属性只能写在constructor中,而由于原型本质是一个对象,所以可以在原型中添加属性,但我们一般不这样做,原型中一般都放公用方法。
  • 总体来说ES6实现继承更加方便,且便于理解

一个简单的实例

下面是一个通过继承封装的一个简单的弹框例子,仅供理解面向对象编程的实际应用和对于继承的理解。

html:

<div id="alert">
    <div id="info">
        <span>×span>
        <p>这是弹框的标题p>
        <div>这是弹框的主体内容div>
    div>
div>

css:

* {
    margin: 0;
    padding: 0;
}
#alert {
    width: 100%;
    height: 100%;
    position: fixed;
    background: rgba(0, 0, 0, .3);
}
#info {
    width: 500px;
    height: 200px;
    position: absolute;
    left: 50%;
    top: 10%;
    margin-left: -250px;
    background: #eee;
    border-radius: 5px;
    color: #333;
}
#info p {
    height: 20%;
    text-indent: 20px;
    background: #1CB21C;
    border-top-left-radius: 5px;
    border-top-right-radius: 5px;
    color: #fff;
}
#info span {
    position: absolute;
    right: 10px;
    font-size: 28px;
    display: inline-block;
    color: #fff;
    cursor: pointer;
}
#info span:hover {
    color: #eee;
}
#info div {
    height: 80%;
    text-align: center;
    font-size: 30px;
}
#info p:before,  #info div:before {
    content: "";
    display: inline-block;
    height: 100%;
    vertical-align: middle;
}

js部分(ES5实现):

function Alert(opt) {
    if(typeof opt.el !== "string") {
        throw Error("请输入自定义弹框的元素id");
    }

    this._el = document.getElementById(opt.el.slice(1));
    this._info = document.getElementById("info");
    this._title = this._el.getElementsByTagName("p")[0];
    this._content = this._el.querySelector("#info div");
    this._close = this._el.querySelector("#info span");

    this._title.innerHTML = opt.title || "title";
    this._content.innerHTML = opt.content || "content";
    this._autoClose = !!opt.autoClose;

    this._el.onclick = function(e) {
        e.stopPropagation()
        this.close();
    }.bind(this)

    this._info.onclick = function(e) {
        e.stopPropagation()
    }

    this._close.onclick = function() {
        this.close();
    }.bind(this)

    this.close();
}
Alert.prototype = {
    constructor: Alert,
    open: function() {
        this._el.style.display = "block";
        if(this._autoClose) {
            setTimeout(this.close.bind(this), 2000);
        }
        return this;
    },
    close: function() {
        this._el.style.display = "none";
        return this;
    }
}

function Alert_child(opt) {
    Alert.call(this, opt);
    this.props = opt.props || {};
}

function C() {}
C.prototype = Alert.prototype;
Alert_child.prototype = new C();

Alert_child.prototype.render = function() {
    var props = JSON.stringify(this.props).replace(/\s|\r|\n/g, "");
    if(props.length === 2) {
        console.error("props参数为空!")
    } else {
        for(var key in this.props) {
            var propArr = key.split("_");
            var el = "_" + propArr[0];

            this[el].style[propArr[1]] = this.props[key];
        }
    }
    return this;
}

const alert1 = new Alert_child({
    el: "#alert",
    title: "这是一个warning弹框的title", //默认title
    content: "你需要的内容已经新增成功!", //默认content
    autoClose: true, //默认false
    props: {
        title_background: "orange",
        content_fontSize: "18px"
    }
})

document.onclick = function() {
    alert1.render().open();
}

js部分(ES6实现):

class Alert {
    constructor(opt) {
        if(typeof opt.el !== "string") {
            throw Error("请输入自定义弹框的元素id");
        }

        this._el = document.getElementById(opt.el.slice(1));
        this._info = document.getElementById("info");
        this._title = this._el.getElementsByTagName("p")[0];
        this._content = this._el.querySelector("#info div");
        this._close = this._el.querySelector("#info span");

        this._title.innerHTML = opt.title || "title";
        this._content.innerHTML = opt.content || "content";
        this._autoClose = !!opt.autoClose;

        this._el.onclick = function(e) {
            e.stopPropagation()
            this.close();
        }.bind(this)

        this._info.onclick = function(e) {
            e.stopPropagation()
        }

        this._close.onclick = function() {
            this.close();
        }.bind(this)

        this.close();
    }
    open() {
        this._el.style.display = "block";
        if(this._autoClose) {
            setTimeout(this.close.bind(this), 2000);
        }
        return this;
    }
    close() {
        this._el.style.display = "none";
        return this;
    }
}
class Alert_child extends Alert {
    constructor(opt) {
        super(opt);
        this.props = opt.props;
    }
    render() {
        var props = JSON.stringify(this.props).replace(/\s|\r|\n/g, "");
        if(props.length === 2) {
            console.error("props参数为空!")
        } else {
            for(var key in this.props) {
                var propArr = key.split("_");
                var el = "_" + propArr[0];

                this[el].style[propArr[1]] = this.props[key];
            }
        }
        return this;
    }
}
const alert1 = new Alert_child({
    el: "#alert",
    title: "这是一个warning弹框的title", //默认title
    content: "你需要的内容已经新增成功!", //默认content
    autoClose: true, //默认false
    props: {
        title_background: "orange",
        content_fontSize: "18px"
    }
})

document.onclick = function() {
    alert1.render().open();
}

你可能感兴趣的:(javascript原生之美)