的继承在很多书里面细致的分了很多种类型和实现方式,大体上就是两种对象冒充、原型方式。这两种方式各有优点和缺陷,这里我给你先列举出来,再从底层分析区别。当构造对象B的时候,调用temp相当于启动A的构造函数,注意这里的上下文环境中的this对象是B的实例,所以在执行A构造函数脚本时,所有A的变量和方法都会赋值给this所指的对象,即B的实例,这样子就达到B继承了A的属性方法的目的。
javascript继承有哪两种形式
< p > < p >的继承在很多书中分为很多类型和实现方式,一般是对象模拟和原型两种方式。
这两种方法各有优缺点。在这里,我先给大家列举一下,再从底层分析区别。(1)该对象假装是(name){ this . name = name
< p > this。= () {(this.name+"!")}
}B(name,Id){ this . temp = A
< p > this . temp(name) < p >//它相当于newa() < p > this . temp < p >//防止超类A的属性和方法this.id将来被temp引用覆盖。}}构造对象B时,调用temp相当于启动A的构造函数,注意这里上下文中的这个对象是B的一个实例,所以在执行A的构造函数脚本时,A的所有变量和方法都会赋给这个所指向的对象,也就是B的实例,从而达到B继承A的属性方法的目的,删除临时引用temp后, 是为了防止维护B中A的类对象(注意不是实例对象)的引用改变,因为改变temp会直接导致A类的结构改变(注意不是A类的对象)。
我们可以看到,在Js版本更新的过程中,添加了call和apply函数,以便更方便地切换这个上下文来实现继承或更通用的目的。它们的原理是一样的,只是参数的版本不同(一个变量是任意参数,而一个参数集必须传入数组)。这里以call为例说明call实现的对象假装被继承。Rect(width),{this.width=width
this。=
< p > this . area =(){ this . width * this。}
}(width,name){Rect.call(this,width,)
< p > this . name = name < p > this . show =(){ alert(this . name+" With area "+this . area()) < p > }关于调用方法,官方的解释是调用一个对象的方法来使用另一个调用(,arg1,arg2…),这也是对象模拟的继承。实际上,调用call方法时发生的也是上下文环境变量this的替换。在函数体中,这必须指向类对象的实例。但是,使用它作为上下文环境变量会调用Rect方法,即Rect类的构造函数。所以当Rect被调用时,它的赋值属性和方法实际上是在一个新的对象上执行的。因此,尽管call和apply不仅仅是继承的新方法,它们也可以模拟继承。对象模仿继承就是这样的东西,它可以实现多重继承,只需要重复赋值的过程。然而目前并没有大规模使用。为什么?< br >因为它有一个明显的性能缺陷,所以有必要谈谈OO的概念。我们说对象是成员+成员方法的集合。构造对象实例时,这些实例只需要有自己的成员变量。成员方法只是一个对变量进行操作的可执行文本区域。不需要为每个实例复制这个区域,所有实例都可以共享。现在回到Js对模拟对象的继承,所有的成员方法都是为此创建的,也就是说,所有的实例都有一个成员方法的副本,这是对内存资源的极大浪费。其他的缺陷,比如对象冒充变量,方法不能继承域,就不用提了。我觉得前一个致命缺陷就够了。但是我们还是要了解一下,尤其是父类的属性和方法是如何继承的原理,这对理解Js继承非常重要。(二)原型。第二种类型的继承是原型。所谓原型继承,就是通过某种方式使用或覆盖属性方法来复制它。实现的方式有很多种,不同的框架可能会有一些差异,但是如果把握住了原理,就没有什么不懂的了。看一个例子(某种实现)(){this.name = "Mike" < p > this。= () {alert("!")}..=(){alert("你好!(){}。= new ()
< p >重点是将最后一句话中的prototype属性赋给类构造的对象。在这里,作者解释了如何将父类的属性和方法复制到子类中。 < p >当Js对象读取对象的属性时,它总是首先查看自己域的属性列表。如果有,就会返回;否则,它将读取域(每个对象共享域的所有属性和方法