真正意义上来说 并不是一门面向对象的语言,没有提供传统的继承方式,但是它提供了一种原型继承的方式,利用自身提供的原型属性来实现继承。
原型继承
原型继承的定义
当你阅读关于JS原型继承的解释时,你时常会看到以下这段文字:
| 当查找一个对象的属性时, 会向上遍历原型链,直到找到给定名称的属性为止。——出自 秘密花园 |
大多数 的实现用 __proto__ 属性来表示一个对象的原型链。在这篇文章里我们将看到 __proto__与 prototype 的区别何在。
注:__proto__ 是一个不应在你代码中出现的非正规的用法,这里仅仅用它来解释 原型继承的工作原理。
以下代码展示了JS引擎如何查找属性:
function getProperty(obj, prop) {
if (obj.hasOwnProperty(prop))
return obj[prop]
else if (obj.__proto__ !== null)
return getProperty(obj.__proto__, prop)
else
return undefined
}
形式上的理解
类名.prototype.方法名=function(参数){方法体}
< >
function Myclass(x,y){
this.x=x;
this.y=y;
this.say=function(){
p(this.x+\":\"+this.y);
}
}
Myclass.prototype.show=function(){
p(this.x,this.y);
}
var obj1=new Myclass(1,2);
obj1.show();
p(\'show\' in obj1);//true
p(obj1.hasOwnProperty(\'show\')) //false
p(obj1.hasOwnProperty(\'say\')); //true
p(\'show\' in Myclass);//false
p(\"say\" in Myclass);//false
p(typeof Myclass);//function
</ >
原型链
写过继承的人都知道,继承可以多层继承。而在JS中,这种就构成了原型链。那么,原型链是什么?一个实例,至少应该拥有指向原型的proto属性,这是 中的对象系统的基础。不过这个属性是不可见的,我们称之为“内部原型链”,以便和构造器的prototype所组成的“构造器原型链”(亦即我们通常所说的“原型链”)区分开。
原型继承支持一种称为原型链的功能,使用原型链有2个前提
a.所有的函数(对象)都具有名为prototype的属性(prototype属性所引用的对象则称为prototype对象)
【对象实例 如上代码中的obj1没有prototype属性】
< >
p( \'prototype\' in obj1);//false
p(\'__proto__\' in obj1);//true
p(\'prototype\' in Myclass);//true
p(\"__proto__\" in Myclass);//true
</ >
b.所有的对象都含有一个(隐藏的)链接,用以指向在对象生成过程中所使用的构造函数(Function对象)的prototype对象b.所有的对象都含有一个(隐藏的)链接,用以指向在对象生成过程中所使用的构造函数(Function对象)的prototype对象
< >
p(obj1.__proto__===Myclass.prototype);//true
p(Myclass.__proto__);// function Empty() {}
p(obj1.prototype);//undefined
p(\'x\' in Myclass);//false
</ >
js原型继承的几种方式
1. 原型链继承
function Show(){
this.name=\"run\";
}
function Run(){
this.age=\"20\"; //Run继承了Show,通过原型,形成链条
}
Run.prototype=new Show();
var show=new Run();
alert(show.name)//结果:run
2. 构造函数继承(对象冒充继承)
为了解决引用共享和超类型无法传参的问题,我们采用一种叫借用构造函数的技术,或者成为对象冒充(伪造对象、经典继承)的技术来解决这两种问题
function Box(age){
this.name=[\'Lee\',\'Jack\',\'Hello\']
this.age=age;
}
function Desk(age){
Box.call(this,age); //对象冒充,给超类型传参
}
var desk = new Desk(200);
alert(desk.age);//200
alert(desk.name);//[\'Lee\',\'Jack\',\'Hello\']
desk.name.push(\'AAA\'); //添加的新数据,只给 desk
alert(desk.name)//[\'Lee\',\'Jack\',\'Hello\',\'AAA\']
3. 组合继承(原型链继承+构造函数继承)
借用构造函数虽然解决了刚才两种问题, 但没有原型, 复用则无从谈起。 所以, 我们需要原型链+借用构造函数的模式,这种模式成为组合继承。
function Box(age) {
this.name = [\'Lee\', \'Jack\', \'Hello\']
this.age = age;
}
Box.prototype.run = function () {
return this.name + this.age;
};
function Desk(age) {
Box.call(this, age); //对象冒充
}
Desk.prototype = new Box(); //原型链继承
var desk = new Desk(100);
alert(desk.run());
4. 原型式继承
这种继承借助原型并基于已有的对象创建新对象,同时还不必因此创建自定义类型
function obj(o) { //传递一个字面量函数
function F() {} //创建一个构造函数
F.prototype = o; //把字面量函数赋值给构造函数的原型
return new F(); //最终返回出实例化的构造函数
}
var box = { //字面量对象
name : \'Lee\',
arr : [\'哥哥\',\'妹妹\',\'姐姐\']
};
var box1 = obj(box); //传递
alert(box1.name);
box1.name = \'Jack\';
alert(box1.name);
alert(box1.arr);
box1.arr.push(\'父母\');
alert(box1.arr);
var box2 = obj(box); //传递
alert(box2.name);
alert(box2.arr); //引用类型共享了
5. 寄生组合式继承
寄生组合式继承解决了两次调用的问题,组合式继承就会有两次调用的情况
基本模型如下:
function (o) {
function F() {}
F.prototype = o;
return new F();
}
function inheritPrototype(subType, superType) {
var prototype = (superType.prototype); //创建对象
prototype.constructor = subType; //增强对象
subType.prototype = prototype; //指定对象
} 继续阅读与本文标签相同的文章
-
健乐教学机器人可开展的教学实训内容
2026-05-14栏目: 教程
-
5G套餐曝光遭“吐槽”,iphone11受追捧,导致苹果11销量比较高
2026-05-14栏目: 教程
-
为什么修电脑的叫自己不要杀毒和清理垃圾?
2026-05-14栏目: 教程
-
当水乡建筑遇上机器人,成就乌镇又一网红景点
2026-05-14栏目: 教程
-
惊险!手刹失灵,郴州一货车开启“无人驾驶”模式……
2026-05-14栏目: 教程
