最近为了工作,是各种面试笔试在搜罗,在学习!作为工作的历程,从今天开始我会把出现频率比较多的内容记录下来。
为了能进那某某公司,再次多谢共享知识的大神们!
问题:①面向对象编程,b如何继承a。
②javascript面向对象中继承实现
③js如何实现面向对象和继承机制
④...
等等类似这样的问题,主要归类如下:
一.原形链
首先,最常用的是javascript面向对象中的继承实现的构造函数和Prototype原型链,在原型链继承方面,JavaScript与java、c#等语言类似,仅允许单父类继承。基本方式如下两个示例:
View Code
1 function Animal(name) {
2 this.name = name;
3 }
4 Animal.prototype.getName = function() {alert(this.name)}
5 function Dog() {};
6 Dog.prototype = new Animal("Buddy");
7 Dog.prototype.constructor = Dog;
8 var dog = new Dog();
通过对象Child的prototype属性指向父对象Parent的实例,使Child对象实例能通过原型链访问到父对象构造所定义的属性、方法等
function Parent(){}
function Child(){}
Child.prototype = new Parent();
构造通过原型链链接了父级对象,不意味着完成了对象的继承了!child可以作为child实例使用,为了不丢失实例child原有的对象构造信息。强制所有的Child对象实例的构造都为Child,可以向下面这样操作:
function Parent(){}
function Child(){}
Child.prototype = new Parent();
Child.prototype.constructor = Child;
var child = new Child();
alert(child.constructor);//function Parent(){}
alert(child instanceof Child);//true
function Parent(){}
function Child(){}
Child.prototype = new Parent();
var child = new Child();
alert(child.constructor);//function Parent(){}
alert(child instanceof Child);//true
二.apply和call使用
注意:apply的参数使用数组形式,call可以直接使用参数
call方法的使用:
function sayColor(sPrefix,sSuffix){
alert(sPrefix+this.color+sSuffix);
};
var obj=new Object();
obj.color="red";
//outputs "The color is red,a very nice color indeed."
sayColor.call(obj,"The color is ",", a very nice color indeed.")
详细出处参考:http://www.jb51.net/article/23536.htm
apply方法的使用示例:
apply也可以使用this调用sayColor.apply(this,new Array("the color is",",a very nice color indeed.")
function sayColor(sPrefix,sSuffix){
alert(sPrefix+this.color+sSuffix);
};
var obj=new Object();
obj.color="red";
//outputs "The Color is red,a very nice color indeed."
sayColor.apply(obj,new Array("The Color is ",",a very nice color indeed."));
详细出处参考:http://www.jb51.net/article/23536.htm
call和apply:
<script language="javascript">
function testExec()
{
alert("执行!");
}
testExec.call(null);//弹出execute对话框
testExec.apply(null);//弹出execute对话框
</script>
三.对象间的继承
JavaScript对象的多态性,允许实例动态地添加属性、方法。JavaScript严格意义上,多态性与Java,C++的多态性有区别。javascript 中函数的参数是没有类型的,并且参数个数也是任意的。通过函数的 arguments 属性,还可以在函数中通过 instanceof 或者 constructor 来判断每个参数的类型,来决定后面执行什么操作,实现更为复杂的函数或方法重载。(关于这方面还有很多案例值得研究,超出本题范围就点到为止了!)
补充知识:重载的英文是 overload,覆盖的英文是 override。发现网上大多数人把 override 当成了重载,这个是不对的。重载和覆盖是有区别的。重载的意思是,同一个名字的函数(注意这里包括函数)或方法可以有多个实现,他们依靠参数的类型和(或)参数的个数来区分识别。
而覆盖的意思是,子类中可以定义与父类中同名,并且参数类型和个数也相同的方法,这些方法的定义后,在子类的实例化对象中,父类中继承的这些同名方法将被隐藏。
var Person = {name:"nathena",age:"26"};
var nathena = {sex:"male"};
(function inlineExtends(so,po)
{
for (var i in po)
{
if (so[i])//如果so也具有这个成员
continue;
so[i] = po[i];
}
})(nathena,Person);
alert(nathena.name);//返回nathana
可以通过拷贝的方法进行继承,有浅和深拷贝:
知识补充:浅拷贝,如若子对象属性,方法改变,父对象会受到影响。深拷贝,父对象不受子对象的影响
浅拷贝:
function extendCopy(p) {
var c = {};
for (var i in p) {
c[i] = p[i];
}
c.uber = p;
return c;
}
var Doctor = extendCopy(Chinese);
Doctor.career = '医生';
alert(Doctor.nation); // 中国
深拷贝继承:
function deepCopy(p, c) {
var c = c || {};
for (var i in p) {
if (typeof p[i] === 'object') {
c[i] = (p[i].constructor === Array) ? [] : {};
deepCopy(p[i], c[i]);
} else {
c[i] = p[i];
}
}
return c;
}
知识补充:JQuery的继承就利用拷贝原理
四.各种混合的继承机制
实例1:组合模式(构造函数模式与原型模式)
把所有实例不需要共享的属性定义在构造函数中,把需要共享的属性,方法定义在原型中,互补构造函数模式和原型模式的优缺点
原型是所有实例化对象的原型对象,实例与原型之间是通过实例内部属性__proto__连接到原型,所有实例共享原型中的属性和方法,如果构造函数中重新定义了原型中的同名属性、方法,那么实例对象将会调用构造函数中定义的属性与方法。
function CreateObj(name,age){
console.log(this.name);//yjhyjh
this.name = name;
this.age = age;
this.colors = ["a","b"];
}
CreateObj.prototype = {
constructor: CreateObj,
name: "yjhyjh",
sayName: function(){
return this.name;
}
}
var obj1 = new CreateObj("yjh1",23);
var obj2 = new CreateObj("yjh2",23);
alert(obj1.sayName == obj2.sayName);//true
alert(obj1.sayName());//yjh1
alert(obj2.sayName());//yjh2
obj1.colors.push("c");
alert(obj2.colors);//a,b
实例2:继承(实现继承,原型链)
就是把一个构造函数的原型作为另一个构造函数的实例化对象,那么这个实例化原型对象就会继承另一个构造函数的原型属性和方法,这就是所谓的原型链。来自包含引用类型值的原型,原型中定义的属性,方法是所有实例所共享的,Fun2.prototype原型对象是Fun1类型的一个实例。
function Fun1(){
this.name = ["yjh1","yjh2"];
}
Fun1.prototype = {
constructor: Fun1,
sayName: function(){
alert(this.name)
}
}
function Fun2(){}
Fun2.prototype = new Fun1();
var fun2 = new Fun2();
fun2.sayName();//yjh1,yjh2
fun2.name.push("yjh3"); //fun2.name = ["yjh1","yjh2","yjh3"];
var fun3 = new Fun2();
alert(fun3.name);//yjh1,yjh2,yjh3
实例3:组合继承(继承与借用构造函数)
由于构造函数中定义的属性,方法不是所有实例共享的,而且会覆盖原型中定义的属性与方法,所以它不会由于实例化原型对象(Fun2.prototype)中包含了引用类型值的属性而存在的问题
function Fun1(){
this.name = ["yjh1","yjh2"];
}
Fun1.prototype = {
constructor: Fun1,
sayName: function(){
alert(this.name)
}
}
function Fun2(){
Fun1.call(this);
}
Fun2.prototype = new Fun1();
var fun2 = new Fun2();
fun2.sayName();//yjh1,yjh2
fun2.name.push("yjh3"); //fun2.name = ["yjh1","yjh2","yjh3"];
var fun3 = new Fun2();
alert(fun2.name);//yjh1,yjh2,yjh3
alert(fun3.name);//yjh1,yjh2