再谈javascript原型承接,javascript原型承接

作者:ca88

归咎上边装有的设想,Javascript继承的切切实实贯彻如下,这里只思考了Child和Parent都是函数的情况下:

再谈javascript原型承接,javascript原型承接

的确含义上来讲Javascript并不是一门面向对象的语言,未有提供守旧的存在延续情势,然则它提供了一种原型承袭的法子,利用本人提供的原型属性来兑现一而再。

原型与原型链

说原型承接此前如故要先说说原型和原型链,毕竟那是贯彻原型承袭的基本功。
在Javascript中,每种函数都有一个原型属性prototype指向本身的原型,而由那么些函数创立的对象也可能有一个__proto__脾气指向这一个原型,而函数的原型是三个对象,所以这么些指标也是有二个__proto__针对本身的原型,那样逐层深切直到Object对象的原型,这样就产生了原型链。上边那张图很好的表达了Javascript中的原型和原型链的关联。

图片 1

各样函数都以Function函数创立的靶子,所以每一种函数也许有叁个__proto__品质指向Function函数的原型。这里须要建议的是,真正产生原型链的是每一个对象的__proto__个性,而不是函数的prototype属性,那是很主要的。

原型承继

基本方式

复制代码 代码如下:

var Parent = function(){
    this.name = 'parent' ;
} ;
Parent.prototype.getName = function(){
    return this.name ;
} ;
Parent.prototype.obj = {a : 1} ;

var Child = function(){
    this.name = 'child' ;
} ;
Child.prototype = new Parent() ;

var parent = new Parent() ;
var child = new Child() ;

console.log(parent.getName()) ; //parent
console.log(child.getName()) ; //child

这种是最简易完成原型承接的方法,间接把父类的目的赋值给子类构造函数的原型,那样子类的靶子就能够访问到父类以及父类构造函数的prototype中的属性。 这种办法的原型承袭图如下:

图片 2

这种办法的长处很肯定,完成足够差不离,无需别的非常的操作;同不常候缺点也很令人侧目,如若子类要求做跟父类构造函数中一样的开始化动作,那么就得在子类构造函数中再重新三回父类中的操作:

复制代码 代码如下:

var Parent = function(name){
    this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
    return this.name ;
} ;
Parent.prototype.obj = {a : 1} ;

var Child = function(name){
    this.name = name || 'child' ;
} ;
Child.prototype = new Parent() ;

var parent = new Parent('myParent') ;
var child = new Child('myChild') ;

console.log(parent.getName()) ; //myParent
console.log(child.getName()) ; //myChild

上边这种状态还只是亟需开首化name属性,假如开始化职业不断充实,这种艺术是很不便利的。因此就有了上边一种创新的不二法门。

借用构造函数

复制代码 代码如下:

var Parent = function(name){
    this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
    return this.name ;
} ;
Parent.prototype.obj = {a : 1} ;

var Child = function(name){
    Parent.apply(this,arguments) ;
} ;
Child.prototype = new Parent() ;

var parent = new Parent('myParent') ;
var child = new Child('myChild') ;

console.log(parent.getName()) ; //myParent
console.log(child.getName()) ; //myChild

下面这种格局在子类构造函数中经过apply调用父类的构造函数来拓展同样的初步化专门的学问,那样无论父类中做了某个初步化专门的学业,子类也能够奉行同一的开首化专门的学业。然而下边这种达成还留存多少个标题,父类构造函数被实行了一次,三次是在子类构造函数中,三遍在赋值子类原型时,那是好些个余的,所以大家还索要做贰个改良:

复制代码 代码如下:

var Parent = function(name){
    this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
    return this.name ;
} ;
Parent.prototype.obj = {a : 1} ;

var Child = function(name){
    Parent.apply(this,arguments) ;
} ;
Child.prototype = Parent.prototype ;

var parent = new Parent('myParent') ;
var child = new Child('myChild') ;

console.log(parent.getName()) ; //myParent
console.log(child.getName()) ; //myChild

诸如此类大家就只必要在子类构造函数中施行一遍父类的构造函数,同一时间又能够一连父类原型中的属性,那也比较适合原型的初衷,正是把供给复用的剧情放在原型中,我们也只是持续了原型中可复用的从头到尾的经过。上边这种办法的原型图如下:

图片 3

临时构造函数形式(圣杯形式)

上边借用构造函数形式最终改正的本子照旧存在难题,它把父类的原型间接赋值给子类的原型,那就能够导致三个难题,就是如果对子类的原型做了退换,那么那么些修改同时也会影响到父类的原型,进而影响父类对象,这一个一定不是我们所期待看到的。为了缓慢解决那么些主题素材就有了临时构造函数形式。

复制代码 代码如下:

var Parent = function(name){
    this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
    return this.name ;
} ;
Parent.prototype.obj = {a : 1} ;

var Child = function(name){
    Parent.apply(this,arguments) ;
} ;
var F = new Function(){} ;
F.prototype = Parent.prototype ;
Child.prototype = new F() ;

var parent = new Parent('myParent') ;
var child = new Child('myChild') ;

console.log(parent.getName()) ; //myParent
console.log(child.getName()) ; //myChild

该措施的原型承接图如下:

图片 4

很轻巧可以见见,通过在父类原型和子类原型之间投入三个一时的构造函数F,切断了子类原型和父类原型之间的关联,那样当子类原型做修改时就不会潜移默化到父类原型。

自己的章程

《Javascript情势》中到圣杯情势就终止了,可是不管下边哪个种类办法都有四个不易于被察觉的主题素材。咱们能够看看作者在'Parent'的prototype属性中投入了一个obj对象字面量属性,可是平素都未有用。大家在圣杯情势的基础上来看望下边这种气象:

复制代码 代码如下:

var Parent = function(name){
    this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
    return this.name ;
} ;
Parent.prototype.obj = {a : 1} ;

var Child = function(name){
    Parent.apply(this,arguments) ;
} ;
var F = new Function(){} ;
F.prototype = Parent.prototype ;
Child.prototype = new F() ;

var parent = new Parent('myParent') ;
var child = new Child('myChild') ;

console.log(child.obj.a) ; //1
console.log(parent.obj.a) ; //1
child.obj.a = 2 ;
console.log(child.obj.a) ; //2
console.log(parent.obj.a) ; //2

在地方这种气象中,当自个儿修改child对象obj.a的时候,同一时间父类的原型中的obj.a也会被退换,那就发出了和共享原型同样的难题。出现这么些状态是因为当访问child.obj.a的时候,大家会顺着原型链一向找到父类的prototype中,然后找到了obj属性,然后对obj.a举行改造。再看看下边这种情景:

复制代码 代码如下:

var Parent = function(name){
    this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
    return this.name ;
} ;
Parent.prototype.obj = {a : 1} ;

var Child = function(name){
    Parent.apply(this,arguments) ;
} ;
var F = new Function(){} ;
F.prototype = Parent.prototype ;
Child.prototype = new F() ;

var parent = new Parent('myParent') ;
var child = new Child('myChild') ;

console.log(child.obj.a) ; //1
console.log(parent.obj.a) ; //1
child.obj.a = 2 ;
console.log(child.obj.a) ; //2
console.log(parent.obj.a) ; //2

那边有一个要害的标题,当目的访问原型中的属性时,原型中的属性对于目的的话是只读的,也正是说child对象可以读取obj对象,但是力不从心修改原型中obj对象引用,所以当child修改obj的时候并不会对原型中的obj产生影响,它只是在自己对象增多了二个obj属性,覆盖了父类原型中的obj属性。而当child对象修改obj.a时,它先读取了原型中obj的引用,那时候child.obj和Parent.prototype.obj是指向同八个对象的,所以child对obj.a的改换会潜移默化到Parent.prototype.obj.a的值,进而影响父类的靶子。AngularJS中关于$scope嵌套的继续格局正是轨范Javasript中的原型承接来落到实处的。
依靠地点的叙说,只要子类对象中访问到的原型跟父类原型是同一个指标,那么就能够产出上面这种状态,所以咱们能够对父类原型举办拷贝然后再赋值给子类原型,那样当子类修改原型中的属性时就只是修改父类原型的一个拷贝,并不会潜移默化到父类原型。具体落实如下:

复制代码 代码如下:

var deepClone = function(source,target){
    source = source || {} ;
    var toStr = Object.prototype.toString ,
        arrStr = '[object array]' ;
    for(var i in source){
        if(source.hasOwnProperty(i)){
            var item = source[i] ;
            if(typeof item === 'object'){
                target[i] = (toStr.apply(item).toLowerCase() === arrStr) : [] ? {} ;
                deepClone(item,target[i]) ;   
            }else{
                deepClone(item,target[i]) ;
            }
        }
    }
    return target ;
} ;
var Parent = function(name){
    this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
    return this.name ;
} ;
Parent.prototype.obj = {a : '1'} ;

var Child = function(name){
    Parent.apply(this,arguments) ;
} ;
Child.prototype = deepClone(Parent.prototype) ;

var child = new Child('child') ;
var parent = new Parent('parent') ;

console.log(child.obj.a) ; //1
console.log(parent.obj.a) ; //1
child.obj.a = '2' ;
console.log(child.obj.a) ; //2
console.log(parent.obj.a) ; //1

归咎下边装有的考虑,Javascript承袭的求实达成如下,这里只思量了Child和Parent都是函数的场所下:

复制代码 代码如下:

var deepClone = function(source,target){
    source = source || {} ;
    var toStr = Object.prototype.toString ,
        arrStr = '[object array]' ;
    for(var i in source){
        if(source.hasOwnProperty(i)){
            var item = source[i] ;
            if(typeof item === 'object'){
                target[i] = (toStr.apply(item).toLowerCase() === arrStr) : [] ? {} ;
                deepClone(item,target[i]) ;   
            }else{
                deepClone(item,target[i]) ;
            }
        }
    }
    return target ;
} ;

var extend = function(Parent,Child){
    Child = Child || function(){} ;
    if(Parent === undefined)
        return Child ;
    //借用父类构造函数
    Child = function(){
        Parent.apply(this,argument) ;
    } ;
    //通过深拷贝承袭父类原型   
    Child.prototype = deepClone(Parent.prototype) ;
    //重置constructor属性
    Child.prototype.constructor = Child ;
} ;

总结

说了如此多,其实Javascript中贯彻持续是至极灵活八种的,并不曾一种最棒的不二等秘书籍,须求基于不一样的需求实现分歧方法的继续,最关键的是要明了Javascript中贯彻延续的法则,也正是原型和原型链的难题,只要精通了那几个,本身实现一而再就可以游刃有余。

真正含义上来讲Javascript并不是一门面向对象的语言,未有提供守旧的继续情势,可是它提供了一种...

图片 5

上面这种艺术在子类构造函数中经过apply调用父类的构造函数来拓展同样的初阶化职业,那样无论父类中做了有一点起初化职业,子类也能够实行同一的起始化专门的工作。不过上边这种完毕还留存三个标题,父类构造函数被实行了一回,贰遍是在子类构造函数中,壹回在赋值子类原型时,那是许多余的,所以我们还索要做几个更上一层楼:

更加多关于JavaScript相关内容感兴趣的读者可查阅本站专项论题:《javascript面向对象入门教程》、《JavaScript错误与调整技术总括》、《JavaScript数据结构与算法本事计算》、《JavaScript遍历算法与技巧总括》及《JavaScript数学生运动算用法总计》

借用构造函数

var Parent = function(name){
    this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
    return this.name ;
} ;
Parent.prototype.obj = {a : 1} ;

var Child = function(name){
    Parent.apply(this,arguments) ;
} ;
Child.prototype = new Parent() ;

var parent = new Parent('myParent') ;
var child = new Child('myChild') ;

console.log(parent.getName()) ; //myParent
console.log(child.getName()) ; //myChild

位置这种措施在子类构造函数中经过apply调用父类的构造函数进行一样的开头化职业,那样不管父类做了略微起先化工作,子类也得以进行一样的发轫化工作。不过地点这种完结还留存七个题目,父类构造函数被施行了三次,贰回是在子类构造函数中,贰遍是在赋值子类原型时,这是许多余的,大家还亟需二次革新:

var Parent = function(name){
    this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
    return this.name ;
} ;
Parent.prototype.obj = {a : 1} ;

var Child = function(name){
    Parent.apply(this,arguments) ;
} ;
Child.prototype = Parent.prototype ;

var parent = new Parent('myParent') ;
var child = new Child('myChild') ;

console.log(parent.getName()) ; //myParent
console.log(child.getName()) ; //myChild

如此那般我们就只须求在子类构造函数中实施二遍父类的构造函数,同不日常候又足以持续父类原型中的属性,那正如相符原型的初衷,正是索要复用的内容放在原型中,大家也只是三番五次了原型中可复用的故事情节。上边这种艺术的原型图如下:

图片 6

图片.png

var Child = function(name){
    Parent.apply(this,arguments) ;
} ;
var F = new Function(){} ;
F.prototype = Parent.prototype ;
Child.prototype = new F() ;

var Parent = function(name){
  this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
  return this.name ;
} ;
Parent.prototype.obj = {a : 1} ;
var Child = function(name){
  Parent.apply(this,arguments) ;
} ;
var F = new Function(){} ;
F.prototype = Parent.prototype ;
Child.prototype = new F() ;
var parent = new Parent('myParent') ;
var child = new Child('myChild') ;
console.log(child.obj.a) ; //1
console.log(parent.obj.a) ; //1
child.obj.a = 2 ;
console.log(child.obj.a) ; //2
console.log(parent.obj.a) ; //2

原型承接

总结

个体综合方式

大神的做法

《javascript格局》中圣杯形式就归西了,可是不管上边哪个种类办法都有三个不便于被开掘的难题。我们能够看到自家在Parent的prototype属性中投入了贰个obj对象字面量属性,可是平素未有用,大家在圣杯形式的基本功上来看望上面这种气象:

var Parent = function(name){
    this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
    return this.name ;
} ;
Parent.prototype.obj = {a : 1} ;

var Child = function(name){
    Parent.apply(this,arguments) ;
} ;
var F = function(){} ;
F.prototype = Parent.prototype ;
Child.prototype = new F() ;

var parent = new Parent('myParent') ;
var child = new Child('myChild') ;

console.log(child.obj.a) ; //1
console.log(parent.obj.a) ; //1
child.obj.a = 2 ;
console.log(child.obj.a) ; //2
console.log(parent.obj.a) ; //2

在地点这种状态中,当自个儿修改child对象obj.a的时候,相同的时候父类原型中的obj.a也会被改动,那就发生了和共享原型同样的难点。出现那个境况是因为当访问child.obj.a的时候,大家会沿着原型链一向找到父类的prototype中,然后找到了obj属性,然后对obj.a进行改造。
此间有一个最重要的标题,当对象访问原型中的属性时,原型中的属性对于目的的话是只读的,也正是说child对象能够读取obj对象,不过不可能修改原型中obj对象引用,所以当child修改obj的时候并不会对原型中的obj产生影响,它只是在自身对象增添了多个obj属性,覆盖了父类原型中的obj属性。而当child对象修改obj.a时,它先读取了原型中obj的引用,那时候child.obj和Parent.prototype.obj是指向同贰个对象的,所以child对obj.a的修改会影响到Parent.prototype.obj.a的值,进而影响到父类的靶子。AngularJS中关于$scope嵌套的接续形式正是人云亦云Javascript中的原型承袭来完成的。
依据下面的叙述,只要子类对象中访问的原型跟父类原型是同一个指标,那么就能产出上边这种气象,所以大家得以对父类原型举办拷贝然后再赋值给子类原型,这样当子类修改原型中的属性时便是修改父类原型的叁个正片,并不会潜移默化父类原型,具体落实如下:

var deepClone = function(source,target){
    source = source || {} ;
    target = target || {};
    var toStr = Object.prototype.toString ,
        arrStr = '[object array]' ;
    for(var i in source){
        if(source.hasOwnProperty(i)){
            var item = source[i] ;
            if(typeof item === 'object'){
                target[i] = (toStr.apply(item).toLowerCase() === arrStr) ? [] : {} ;
                deepClone(item,target[i]) ;    
            }else{
                target[i] = item;
            }
        }
    }
    return target ;
} ;
var Parent = function(name){
    this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
    return this.name ;
} ;
Parent.prototype.obj = {a : '1'} ;

var Child = function(name){
    Parent.apply(this,arguments) ;
} ;
Child.prototype = deepClone(Parent.prototype) ;

var child = new Child('child') ;
var parent = new Parent('parent') ;

console.log(child.obj.a) ; //1
console.log(parent.obj.a) ; //1
child.obj.a = '2' ;
console.log(child.obj.a) ; //2
console.log(parent.obj.a) ; //1

综上所述下面的设想,javascript承继的求实完结如下,这里只考虑了Child和Parent都是函数的意况下:

var deepClone = function(source,target){
    source = source || {} ;
    target = target || {};
    var toStr = Object.prototype.toString ,
        arrStr = '[object array]' ;
    for(var i in source){
        if(source.hasOwnProperty(i)){
            var item = source[i] ;
            if(typeof item === 'object'){
                target[i] = (toStr.apply(item).toLowerCase() === arrStr) ? [] : {} ;
                deepClone(item,target[i]) ;    
            }else{
                target[i] = item;
            }
        }
    }
    return target ;
} ;

var extend = function(Parent,Child){
    Child = Child || function(){} ;
    if(Parent === undefined)
        return Child ;
    //借用父类构造函数
    Child = function(){
        Parent.apply(this,argument) ;
    } ;
    //通过深拷贝继承父类原型    
    Child.prototype = deepClone(Parent.prototype) ;
    //重置constructor属性
    Child.prototype.constructor = Child ;
} ;

参考自:https://segmentfault.com/a/1190000000766541

var Parent = function(name){
    this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
    return this.name ;
} ;
Parent.prototype.obj = {a : 1} ;

var deepClone = function(source,target){
  source = source || {} ;
  target = target || {};
  var toStr = Object.prototype.toString ,
    arrStr = '[object array]' ;
  for(var i in source){
    if(source.hasOwnProperty(i)){
      var item = source[i] ;
      if(typeof item === 'object'){
        target[i] = (toStr.apply(item).toLowerCase() === arrStr) ? [] : {} ;
        deepClone(item,target[i]) ;
      }else{
        target[i] = item;
      }
    }
  }
  return target ;
} ;
var extend = function(Parent,Child){
  Child = Child || function(){} ;
  if(Parent === undefined)
    return Child ;
  //借用父类构造函数
  Child = function(){
    Parent.apply(this,argument) ;
  } ;
  //通过深拷贝继承父类原型
  Child.prototype = deepClone(Parent.prototype) ;
  //重置constructor属性
  Child.prototype.constructor = Child ;
} ;

种种函数都以Function函数成立的靶子,所以每一个函数也会有贰个proto品质指向Function函数的原型。这里要求指正的是,真正形成原型链的是各类对象的proto特性,而不是函数的prototype属性,那是很关键的。

有时构造函数形式(圣杯格局)

var deepClone = function(source,target){
  source = source || {} ;
  target = target || {};
  var toStr = Object.prototype.toString ,
    arrStr = '[object array]' ;
  for(var i in source){
    if(source.hasOwnProperty(i)){
      var item = source[i] ;
      if(typeof item === 'object'){
        target[i] = (toStr.apply(item).toLowerCase() === arrStr) ? [] : {} ;
        deepClone(item,target[i]) ;
      }else{
        target[i] = item;
      }
    }
  }
  return target ;
} ;
var Parent = function(name){
  this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
  return this.name ;
} ;
Parent.prototype.obj = {a : '1'} ;
var Child = function(name){
  Parent.apply(this,arguments) ;
} ;
Child.prototype = deepClone(Parent.prototype) ;
var child = new Child('child') ;
var parent = new Parent('parent') ;
console.log(child.obj.a) ; //1
console.log(parent.obj.a) ; //1
child.obj.a = '2' ;
console.log(child.obj.a) ; //2
console.log(parent.obj.a) ; //1

图片.png

复制代码 代码如下:

以下就是原型链和原型的关联,引用网上的一张图

在javascript中,每一个函数都有三个原型属性prototype指向函数本身的原型,而由那个函数创建的对象也是有四个proto性格指向这一个原型,而函数的原型是一个对象,所以这么些目的也会有二个proto本着本身的原型,那样逐层深切理解Object对象的原型(null),就形成了原型链。

复制代码 代码如下:

Javascript模式》中到圣杯格局就甘休了,可是无论上边哪种艺术都有多个不便于被开掘的难题。我们能够看看小编在'Parent'的prototype属性中到场了三个obj对象字面量属性,可是一向都未曾用。我们在圣杯情势的基础上来探视下边这种状态:

基本情势

var Parent = function(){
    this.name = 'Parent';
}
Parent.prototype.getName = function(){
    return this.name;
}
Parent.prototype.obj={a:1};

var Child = function(){
    this.name='child';
}
Child.prototype = new Parent();
var parent = new Parent();
var child = new Child();

console.log(parent.getName()); //parent
console.log(child.getName()); //child

这种办法的原型传承图如下:

图片 7

图片.png

这种方法优点很刚毅,完结丰硕回顾,不必要别的异样的操作;同不平时间缺点也很明显,要是子类要求做跟父类构造函数中平等的初始化动作,那么就得在子类构造函数中再重新一遍父类中的操作:

var Parent = function(name){
    this.name = name || 'Parent';
}
Parent.prototype.getName = function(){
    return this.name;
}
Parent.prototype.obj={a:1};

var Child = function(name){
    this.name=name || 'child';
}
Child.prototype = new Parent();
var parent = new Parent('myParent');
var child = new Child('myChild');

console.log(parent.getName()); //myparent
console.log(child.getName()); //myChild

地方这种状态还只是内需开首化name属性,假若起先化专门的学业不断增添,这种方法不是很方便,所以就有了上面这种立异措施:

console.log(child.obj.a) ; //1
console.log(parent.obj.a) ; //1
child.obj.a = 2 ;
console.log(child.obj.a) ; //2
console.log(parent.obj.a) ; //2

如此大家就只须要在子类构造函数中实行叁遍父类的构造函数,同不时间又足以一而再父类原型中的属性,那也正如吻合原型的初衷,就是把需求复用的内容放在原型中,大家也只是延续了原型中可复用的剧情。

偶尔构造函数格局(圣杯形式)

地方借用构造函数方式最终改进的版本依然存在难题,它把父类的原型直接赋值给子类的原型,就能够促成一个主题素材,正是一旦对子类的原型做了改变,那么这几个修改同不平日间也会潜移默化到父类的原型,进而影响父类对象,那个一定不是豪门所企望观察的,为了消除这一个题目就有了一时构造函数情势。

var Parent = function(name){
    this.name = name || 'Parent';
}
Parent.prototype.getName = function(){
    return this.name;
}
Parent.prototype.obj={a:1};

var Child = function(name){
    Parent.apply(this,arguments);
}

var F = function(){}
F.prototype = Parent.prototype;
Child.prototype = new F();
var parent = new Parent('myParent');
var child = new Child('myChild');

console.log(parent.getName()); //myparent
console.log(child.getName()); //myChild

图片 8

图片.png

很轻便可以旁观,通过在父类原型和子类原型之间进入一个有的时候的构造函数F,切断了子类原型和父类原型之间的牵连,这样,当子类原型做修改时就不会潜移默化到父类原型。

var parent = new Parent('myParent') ;
var child = new Child('myChild') ;

var Parent = function(name){
  this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
  return this.name ;
} ;
Parent.prototype.obj = {a : 1} ;
var Child = function(name){
  Parent.apply(this,arguments) ;
} ;
var F = new Function(){} ;
F.prototype = Parent.prototype ;
Child.prototype = new F() ;
var parent = new Parent('myParent') ;
var child = new Child('myChild') ;
console.log(child.obj.a) ; //1
console.log(parent.obj.a) ; //1
child.obj.a = 2 ;
console.log(child.obj.a) ; //2
console.log(parent.obj.a) ; //2

《Javascript形式》中到圣杯形式就得了了,不过不管上边哪个种类办法都有三个不便于被发掘的难题。大家能够看看本人在'Parent'的prototype属性中投入了四个obj对象字面量属性,不过一贯都尚未用。大家在圣杯情势的基础上来看望上面这种情形:

正文实例讲述了JavaScript使用原型和原型链达成指标承继的方式。分享给大家供大家参考,具体如下:

复制代码 代码如下:

此办法有优点也可能有缺点,承继的贯彻很简短,代码轻松轻巧精晓,可是子类承继父类的积极分子变量须求自身再也开始化,也等于父类有微微个分子变量,在子类中还索要重新定义及起首化

这种是最简便易行落成原型承继的主意,直接把父类的对象赋值给子类构造函数的原型,这样子类的指标就能够访问到父类以及父类构造函数的prototype中的属性。 这种格局的原型承袭图如下:

地点这种气象还只是急需初步化name属性,假如发轫化专业持续追加,这种格局是很不便于的。因而就有了下边一种创新的办法。

该格局的原型承继图如下:

据书上说上边的叙述,只要子类对象中做客到的原型跟父类原型是同贰个目的,那么就能够油但是生上边这种处境,所以大家得以对父类原型进行拷贝然后再赋值给子类原型,那样当子类修改原型中的属性时就只是修改父类原型的多少个正片,并不会潜移默化到父类原型。具体落到实处如下:

var Parent = function(name){
    this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
    return this.name ;
} ;
Parent.prototype.obj = {a : 1} ;

愿意本文所述对我们JavaScript程序设计具有支持。

var deepClone = function(source,target){
    source = source || {} ;
    var toStr = Object.prototype.toString ,
        arrStr = '[object array]' ;
    for(var i in source){
        if(source.hasOwnProperty(i)){
            var item = source[i] ;
            if(typeof item === 'object'){
                target[i] = (toStr.apply(item).toLowerCase() === arrStr) : [] ? {} ;
                deepClone(item,target[i]) ;   
            }else{
                deepClone(item,target[i]) ;
            }
        }
    }
    return target ;
} ;
var Parent = function(name){
    this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
    return this.name ;
} ;
Parent.prototype.obj = {a : '1'} ;

var Parent = function(name){
  this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
  return this.name ;
} ;
Parent.prototype.obj = {a : 1} ;
var Child = function(name){
  Parent.apply(this,arguments) ;
} ;
var F = new Function(){} ;
F.prototype = Parent.prototype ;
Child.prototype = new F() ;
var parent = new Parent('myParent') ;
var child = new Child('myChild') ;
console.log(parent.getName()) ; //myParent
console.log(child.getName()) ; //myChild

var parent = new Parent('myParent') ;
var child = new Child('myChild') ;

var Parent = function(name){
  this.name = name || 'parent' ;
} ;
Parent.prototype.getName = function(){
  return this.name ;
} ;
Parent.prototype.obj = {a : 1} ;
var Child = function(name){
  Parent.apply(this,arguments) ;
} ;
Child.prototype = Parent.prototype ;
var parent = new Parent('myParent') ;
var child = new Child('myChild') ;
console.log(parent.getName()) ; //myParent
console.log(child.getName()) ; //myChild

这种措施的独到之处很分明,达成丰裕简易,没有须求任何例外的操作;同有难题间缺点也很明显,要是子类须要做跟父类构造函数中同样的开首化动作,那么就得在子类构造函数中再另行三回父类中的操作:

这里有二个第一的难题,当对象访问原型中的属性时,原型中的属性对于指标的话是只读的,也正是说child对象可以读取obj对象,可是不能够修改原型中obj对象引用,所以当child修改obj的时候并不会对原型中的obj发生震慑,它只是在作者对象增多了二个obj属性,覆盖了父类原型中的obj属性。而当child对象修改obj.a时,它先读取了原型中obj的引用,那时候child.obj和Parent.prototype.obj是指向同三个对象的,所以child对obj.a的退换会潜移默化到Parent.prototype.obj.a的值,进而影响父类的指标。AngularJS中有关$scope嵌套的存在延续格局正是楷模Javasript中的原型继承来落到实处的。

复制代码 代码如下:

本文由ca88发布,转载请注明来源

关键词: ca88网址 javascript 亚洲城ca88手