1.最基本的用法 把ClassA的一个实例赋值给ClassB,
ClassB就继承了ClassA的所有属性。
代码入下:
2.从原型继承理论的角度去考虑,
js的原型继承是引用原型,不是复制原型,
所以,修改原型会导致所有B的实例的变化。
代码如下:
3.然而 子类对象的写操作只访问子类对象中成员,
它们之间不会互相影响,因此,
写是写子类 读是读原型(如果子类中没有的话)。
4.每个子类对象都执有同一个原型的引用,
所以子类对象中的原型成员实际是同一个。
5.构造子类时 原型的构造函数不会被执行
6.接下来是致命的,在子类对象中访问原型的成员对象:
7.所以 在prototype继承中 原型类中不能有成员对象! 所有成员必须是值类型数据(string也可以)
用prototype继承有执行效率高,不会浪费内存,为父类动态添置方法后子类中马上可见等的优点。
8.prototype继承是通过把子类的原型对象(prototype)设置成父类的一个实例来进行继承的。
9.prototype继承也有四个比较明显的缺点:
缺点一:父类的构造函数不是像JAVA中那样在给子类进行实例化时执行的,而是在设置继承的时候执行的,并且只执行一次。这往往不是我们希望的,特别是父类的构造函数中有一些特殊操作的情况下。
缺点二:由于父类的构造函数不是在子类进行实例化时执行,在父类的构造函数中设置的成员变量到了子类中就成了所有实例对象公有的公共变量。由于JavaScript中继承只发生在“获取”属性的值时,对于属性的值是String,Number和Boolean这些数据本身不能被修改的类型时没有什么影响。但是Array和Object类型就会有问题。
缺点三:如果父类的构造函数需要参数,我们就没有办法了。
缺点四:子类原本的原型对象被替换了,子类本身的constructor属性就没有了。在类的实例取它的constructor属性时,取得的是从父类中继承的constructor属性,从而constructor的值是父类而不是子类。
10.可以针对prototype的缺点进行改造
比如把它写成Function对象的一个方法,这样用的时候方便。
针对第3,6个
针对继承,
Array.prototype 就不能继承 ClassA,ClassB
利用 apply call 实现继承方法
ClassB就继承了ClassA的所有属性。
代码入下:
<script type="text/javascript">
function ClassA() {
this.a = 'a';
}
function ClassB() {
this.b = 'b';
}
ClassB.prototype = new ClassA();
var objB = new ClassB();
for (var p in objB)//输出为 "ba"
document.write(p + "");
</script>
2.从原型继承理论的角度去考虑,
js的原型继承是引用原型,不是复制原型,
所以,修改原型会导致所有B的实例的变化。
代码如下:
<script>
function ClassA() {
this.a = 'a';
}
function ClassB() {
this.b = 'b';
}
ClassB.prototype = new ClassA();
var objB = new ClassB();
alert(objB.a);//输出 "a"
ClassB.prototype.a = 'changed!!';
alert(objB.a);//output-> "changed"
var c = new ClassB();
alert(c.a);// output -> "changed"
</script>
3.然而 子类对象的写操作只访问子类对象中成员,
它们之间不会互相影响,因此,
写是写子类 读是读原型(如果子类中没有的话)。
<script>
function ClassA() {
this.a = 'a';
}
function ClassB() {
this.b = 'b';
}
ClassB.prototype = new ClassA();
var objB1 = new ClassB();
var objB2 = new ClassB();
objB1.a = '!!!';//修改新对象的属性并不会影响原型
alert(objB1.a); //output -> "!!!"
alert(objB2.a); //output -> "a"
var newb = new ClassB();
alert(newb.a);// output -> "a"
</script>
4.每个子类对象都执有同一个原型的引用,
所以子类对象中的原型成员实际是同一个。
<script>
function ClassA() {
this.a = function () {
alert("a");
};
}
function ClassB() {
this.b = function () {
alert("b");
};
}
ClassB.prototype = new ClassA();
var objB1 = new ClassB();
var objB2 = new ClassB();
alert(objB1.a == objB2.a);//在没有使用方法之前,被继承的方法都不会执行,所以这儿为true,注意 属性 和 对象 的方式是不一样的,如果是简单属性会立即创建,否则则是到了需要的时候才创建
alert(objB1.b == objB2.b);//子类的方法在对象创建的时候已经分配空间,因为属于不同空间的两个方法,所以为 false
</script>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script type="text/javascript">
var lis = document.getElementsByTagName("li");
for(var index=0;index<lis.length;index++) {
lis[index].addEventListener("click",function(){
this.className = index;
});
}
</script>
当点击每个li的时候,会添加一个class,结果为每次点击li他们的class都是5,这个就很好解释了方法在没有执行前是不会新建空间来保存的,只有等到事件触发了才会去创建空间来保存生成的数据,例子不太好,意思可以从代码中理解出来
5.构造子类时 原型的构造函数不会被执行
<script>
function ClassA() {
alert("a");
this.a = function () {
alert("inner a");
};
}
function ClassB() {
alert("b");
this.b = function () {
alert("innner b");
};
}
ClassB.prototype = new ClassA();
var objB1 = new ClassB();//不会alert
var objB2 = new ClassB();//不会alert
</script>
6.接下来是致命的,在子类对象中访问原型的成员对象:
<script>
function ClassA() {
this.a = [];
}
function ClassB() {
this.b = function () {
alert("");
};
}
ClassB.prototype = new ClassA();
var objB1 = new ClassB();
var objB2 = new ClassB();
objB1.a.push(1, 2, 3);
alert(objB2.a);//所有b的实例中的a成员全都变了!!
</script>
7.所以 在prototype继承中 原型类中不能有成员对象! 所有成员必须是值类型数据(string也可以)
用prototype继承有执行效率高,不会浪费内存,为父类动态添置方法后子类中马上可见等的优点。
8.prototype继承是通过把子类的原型对象(prototype)设置成父类的一个实例来进行继承的。
9.prototype继承也有四个比较明显的缺点:
缺点一:父类的构造函数不是像JAVA中那样在给子类进行实例化时执行的,而是在设置继承的时候执行的,并且只执行一次。这往往不是我们希望的,特别是父类的构造函数中有一些特殊操作的情况下。
缺点二:由于父类的构造函数不是在子类进行实例化时执行,在父类的构造函数中设置的成员变量到了子类中就成了所有实例对象公有的公共变量。由于JavaScript中继承只发生在“获取”属性的值时,对于属性的值是String,Number和Boolean这些数据本身不能被修改的类型时没有什么影响。但是Array和Object类型就会有问题。
缺点三:如果父类的构造函数需要参数,我们就没有办法了。
缺点四:子类原本的原型对象被替换了,子类本身的constructor属性就没有了。在类的实例取它的constructor属性时,取得的是从父类中继承的constructor属性,从而constructor的值是父类而不是子类。
10.可以针对prototype的缺点进行改造
比如把它写成Function对象的一个方法,这样用的时候方便。
Function.prototype.Extends = function (parentClass)
{
var Bs = new Function();
Bs.prototype = parentClass.prototype;
this.prototype = new Bs();
this.prototype.Super = parentClass;
this.prototype.constructor = this;
}
针对第3,6个
<script>
function ClassA() {
this.a = [];
this.aa = 100;
}
function ClassB() {
this.b = function () {
return "classb"
};
}
ClassB.prototype = new ClassA();
var objB1 = new ClassB();
var objB2 = new ClassB();
objB1.a.push(1, 2, 3);
objB1.aa = 10100;
alert(objB2.a);//1,2,3 a是对象类型
alert(objB2.aa);//100 aa 是基本数据类型
</script>
针对继承,
Array.prototype 就不能继承 ClassA,ClassB
<script>
function ClassA() {
this.a = [];
this.aa = 100;
}
function ClassB() {
this.b = function () {
return "b"
};
}
ClassB.prototype = new ClassA();
Array.prototype = new ClassB();
var _array = new Array();
alert(_array.b());//[i]Uncaught TypeError: Object [object Array] has no method 'b' [/i]
</script>
利用 apply call 实现继承方法
<script type="text/javascript">
function classA () {
this.x = 1;
this.y = 2;
}
function classB() {
this.z = 3;
}
classB.prototype = new classA();
var b = new classB();
alert(b.x+ b.z);
</script>