严格来说,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新增了一个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实现继承要方便多了
下面是我总结的以上两种方式实现面向对象继承的不同之处:
Father.fn = function(){}
;ES6通过static关键字添加静态方法class Father {
constructor(opt) {
this.name = opt.name;
this.age = opt.age;
this.height = opt.height;
}
static sleep () {
}
}
下面是一个通过继承封装的一个简单的弹框例子,仅供理解面向对象编程的实际应用和对于继承的理解。
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();
}