这几天公司招聘前端,来面试的前端被问到javascript的原型链和继承,居然没人回答对。
javascript面向对象编程非常重要,因为一个新手前端工程师很容易把代码写得非常乱,增加阅读和维护的难度。
言归正传,当书写一个重业务逻辑的对象的时候,怎么写:
编写一个员工类
function Employee(name, sal){
//姓名
this.name=name;
//工资
this.sal=sal;
}
//为员工类增加一个行为(方法、成员函数)
Employee.prototype.work=function(){
console.log(this.name+" 正在工作!");
};
var e = new Employee("许文强", 11000);
e.work();//打印 “许文强 正在工作”
不清楚prototype的同学已经懵逼了,做个简单的解释,访问一个对象的属性,如:e.work,首先,js引擎会去查找对象e是否具有work属性,如果有,直接返回,如果没有则查找e.__proto__ 对象。说到这里,可能更加懵逼,对象e什么时候有个__proto__属性。每个对象都会有一个__proto__属性,由js引擎自动产生的,与类prototype属性指向同一个对象。,
。根据上边的原理,我们可以把一个对象的属性分为2种,一种是自身属性,一种是__proto__对象的属性。查找一个对象的属性,如果找不到,则从__proto__对象中一直往下找,直到找不到则返回undefined。
一个__proto__属性向链条一样向上索引,被大家说成“原型链”。
把这个概念理解清楚,我们再来说继承。网上去搜js继承,你会发现有好多种写法,有的写法根本没有实现继承的效果,有的大多数的写法都存在着这样或者那样的弊端,这里给大家推荐一篇博客:http://www.cnblogs.com/humin/p/4556820.html
这篇博客总结了常见几种写法,大家可以仔细分析下利弊,这里我给出一种个人经常使用的一种写法,供大家参考。(继承上一个Employee)
//Manager类继承Employee
function Manager(){
//调用Employee,合并name,sal两个属性为自身属性,
Employee.apply(this,arguments);
//书写自身初始化业务
//....
}
Manager.prototype = {
/**************
*将Employee的原型链挂到Manager之后,
*而不是单纯的使用Manager.prototype=Employee.prototype
*否则为Manager扩展的时候会更改Employee的方法,
*违背OCP原则
**********************/
__proto__:Employee.prototype,
constructor:Manager,
//覆盖的方法
work:function(){
console.log("Working "+this.name);
},
//扩展的方法
say:function(){
//
}
};
var m = new Manager();
m.work();
我也来总结下特点:
1.实现效果与C#,java类似。易于维护和扩展,
2.实现较为复杂,不过这不是一个问题,大家可以使用Object.assign(),封装一个extends函数。