js的继承的实现与代码编写
一、继承
对象的一个类可以从现有的类中派生,并且拥有现有的类的方法或是属性,这和过程叫做继承。被继承的类叫做父类或是基类,继承的类叫做子类。 (一个对象拥有另一个对象的属性和方法)。
在 JavaScript 中,是没有多重继承这个概念的,就像 Java 一样。但在 Dojo 中使用 declare 声明类时,是允许继承自多个类的。
dojo.declare("Aoo",null,{});
dojo.declare("Boo",null,{});
dojo.declare("Foo",[Aoo,Boo],{});
var foo = new Foo();
console.log(foo instanceof Aoo);//true
console.log(foo instanceof Boo);//false
console.log(foo.isInstanceOf(Aoo));//true
console.log(foo.isInstanceOf(Boo));//true
Foo 同时继承自 Aoo 和 Boo,但当使用 instanceof 运算符来检查 foo 是否是 Boo 的实例时,返回的是 false。实际上,在 Dojo 的内部,Foo 仍然只继承自 Aoo,而通过 mixin 机制把 Boo 类中的方法和属性拷贝到 Foo 中,所以当用 instanceof 运算符来检查是否是 Boo 的实例时,会返回 false。所以 Dojo 为每个类的实例添加了一个新的方法叫 isInstanceOf,用这个方法来检查多重继承。
二、object对象
所有的对象都是由这个对象继承而来的,是所有对象的基类。
object的属性和方法
A.属性
1.constructor 对创建对象的函数的引用(指针)。
设定构造函数
var obj=new Object();
obj.constructor
//function Object(){
[native code]
}
var obj=new fun1();
function fun1 () {
this.name="zhangsan";
}
alert(obj.constructor)
//所有对象的默认构造函数
//输出 function fun1 () {
// this.name="zhangsan";
//}
2.prototype 原型,对该函数对象的对象原型的引用。是函数对象的默认属性
var obj=new fun1();
function fun1 () {
this.name="zhangsan";
}
alert(obj.prototype)//undefine
alert(fun1.prototype)//Object
B.方法
1.hasOwnProperty(property) 判断对象是否有某个特定的属性
var obj=new fun1();
function fun1 () {
this.name="zhangsan";
}
obj. hasOwnProperty("nme")//true
2.IsPrototypeOf(object) 判断该对象是否为另一个对象的原型。(用来检测对象的类型)
var arr=new Array();
Array.prototype.isPrototypeOf(arr)
3.运算符instanceof ,准确判断是否为某一类型的对象
arr instanceof Array
4.defineProperty(),修改数据属性的特性,(属性所在对象,"属性名",{描述符对象})。可以通过描述符一次定义多个属性
var person={};
Object.defineProperty(person,"name",{
writable:false,
value:"Tom"
});
alert(person.name);
delete person.name;
alert(person.name);
Object.getOwnPropertyDescriptor(book,"_year");读取属性的特性,返回的是对象。
三、原型链
原型链就是让子对象的原型等于父对象的实例,层层递进,实现实例和原型的链条。
function instance_of(L, R) {//L 表示左表达式,R 表示右表达式
var O = R.prototype;// 取 R 的显示原型
L = L.__proto__;// 取 L 的隐式原型
while (true) {
if (L === null)
return false;
if (O === L)// 这里重点:当 O 严格等于 L 时,返回 true
return true;
L = L.__proto__;
}
}
// 判断 foo 是否是 Foo 类的实例 , 并且是否是其父类型的实例
function Aoo(){}
function Foo(){}
Foo.prototype = new Aoo();//JavaScript 原型继承
var foo = new Foo();
console.log(foo instanceof Foo)//true
console.log(foo instanceof Aoo)//true
Function instanceof Function
// 为了方便表述,首先区分左侧表达式和右侧表达式
FunctionL = Function, FunctionR = Function;
// 下面根据规范逐步推演
O = FunctionR.prototype = Function.prototype
L = FunctionL.__proto__ = Function.prototype
// 第一次判断
O == L
// 返回 true
Foo instanceof Foo
// 为了方便表述,首先区分左侧表达式和右侧表达式
FooL = Foo, FooR = Foo;
// 下面根据规范逐步推演
O = FooR.prototype = Foo.prototype
L = FooL.__proto__ = Function.prototype
// 第一次判断
O != L
// 循环再次查找 L 是否还有 __proto__
L = Function.prototype.__proto__ = Object.prototype
// 第二次判断
O != L
// 再次循环查找 L 是否还有 __proto__
L = Object.prototype.__proto__ = null
// 第三次判断
L == null
// 返回 false
原型模式
function SuperType(){
this.property=true;
}
SuperType.prototype.getSuperValue=function(){
return this.property;
}
function SubType(){
this.subproperty=false;
}
SubType.prototype=new SuperType();
SubType.prototype.getSubValue=function(){
return this.subproperty;
}
var instance=new SubType();
alert(instance.getSuperValue());//true
这里需要注意SubType.prototype对象的constructor属性已经不指向SubType,而是指向SuperType.
原型链的问题:
1.原型链也会遇到原型模式的问题,这里就不多说了。
2.创建子对象的实例时,没有办法在不影响所有对象实例的情况下,给父对象的构造函数传递参数。
四、apply()实现属性和方法继承全部继承
apply : obj1.fun.apply(obj2,[参数1,参数2....]) 让对象1的方法冒充成对象2的方法。
function person (name) {
this.name=name;//this代表window this那个对象引用,就是那个对象的函数function person()
this.say=function () {
alert(this.name)
}
}
function student () {
window.person.cell(this)//this代表zhangsan
}
var zhangsan=new student ();
zhangsan.name;//张三
function student () {
window.person.apply(this,["zhangsan"])//参数以数组形式传递
}
var zhangsan=new student ();
zhangsan.name;
zhangsan.say();
<script type="text/javascript">
function Animal(name,age){
this.name=name;
this.age=age;
this.shout=function(){
alert("我是:"+this.name+",今年:"+this.age);
};
this.action=function(){
alert("会吃");
};
}
function Dog(name,age){
Animal.apply(this, [name,age]);//this当前对象,name传入的参数
}
var jack=new Dog("jack",1);
alert(jack.name);
alert(jack.age);
jack.shout();//调用父类的方法
jack.action();
</script>
五、构造函数call()
call : obj1.fun.call(obj2,参数1......).让对象1的方法冒充成对象2的方法。
function person () {
this.name="张三";
this.say=function () {
alert(this.name)
}
}
function student () {
this.name="李四";
}
var ren=new person ();
var zhangsan=new student ();//也有了say方法
ren.say.call(zhangsan)
function SuperType(){
this.colors=["red","blue","green"];
}
function SubType(){
SuperType.call(this)//或者apply()
}
var instance1=new SubType();
instance1.colors.push("black");
alert(instance1.colors);
var instance2=new SubType();
alert(instance2.colors);
构造函数也可以通过子对象向父对象传递参数
function SuperType(name){
this.name=name
}
function SubType(){
SuperType.call(this,"Tom")//或者apply()
}
var instance1=new SubType();
alert(instance1.name);
六、prototype实现原型继承
我们创建的每一个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,这个对象中包含着所有对象实例的属性和方法,这个对象就是原型对象。通俗的说,原型对象中的方法和属性可以被所有对象的实例所共享,对象实例就不用多次创建相同的方法和属性
function Person(){
};
Person.prototype={
name:"Tom",
age:23,
job:"厨师",
sayName:function(){
alert(this.name);
}
}
var person1=new Person();
person1.sayName();
student的原型对象就等于person对象,拥有了person对象的属性和方法
function person () {
this.name="张三";
this.say=function () {
alert(this.name)
}
}
function student () {
}
student.prototype=new person()
var zhangsan=new student ();
zhangsan.say()
<script type="text/javascript">
function Animal(name,age){
this.name=name;
this.age=age;
this.shout=function(){
alert("我是:"+this.name+",今年:"+this.age);
};
this.action=function(){
alert("会吃");
};
}
function Dog(name,age){
Animal.apply(this, [name,age]);//原型还是Animal
}
Dog.prototype=new Animal();//类型的继承,原型变了不再是Animal
var jack=new Dog("jack",1);
alert(jack.name);
alert(jack.age);
jack.shout();
jack.action();
</script>
七、组合继承
虽然借用构造函数解决了实例共享问题和无法传递参数的问题,但是他做的并不完美,因为所有方法都在构造函数中定义,函数的复用性从何谈起,而且父原型对象中定义的方法,对子对象是不可见的,结果所有类型都只能使用构造函数模式.。
这里再强调一下,构造函数创建的属性是实例私有的,原型创建的属性和方法是实例共享的。
function SuperType(name,colors)
{
this.name=name;
this.colors=colors;
};
SuperType.prototype.sayName=function()
{
alert(this.name);
};
function SubType(age,name,colors)
{
SuperType.call(this,name,colors);
this.age=age;
};
SubType.prototype=new SuperType();
SubType.prototype.sayAge=function()
{
alert(this.age);
};
var person1=new SubType(23,"Tom",["blue","red","green"]);
document.writeln(person1.colors);//来自父对象构造函数
document.writeln(person1.name);//来自父对象构造函数
person1.sayName();//来自父原型对象
document.writeln(person1.age);//来自子对象构造函数
person1.sayAge();//来自子原型对象
八、原型式继承
这种方法并没有使用严格意义的构造函数,而是借助原型可以基于已有的对象创建新对象,同时还不用创建自定义类型来达到这个目的。
以下代码是封装在object函数当中的,在使用的时候直接使用object()
function object (o)//这个o相当于父对象实例
{
function F(){}//这个F相当子对象
F.prototype=o;//继承
return new F();//实例化传出
}
九、Object.create()
create的第二参数是一个对象,其中的属性如果和person重名,则会覆盖person的属性。
var person={
name:"Tom",
age:23,
job:"厨师"
};
var anotherPerson=Object.create(person,{
name:{
value:"Mike"
}
});
alert(anotherPerson.name);
十、寄生式继承
function object (o)//这个o相当于父对象实例
{
function F(){}//这个F相当子对象
F.prototype=o;//继承
return new F();//实例化传出
}
function createAnother(o)
{
var clone=object(o);
clone.sayName=function()
{
alert(this.name)
};
return clone;
}
var person={
name:"Tom",
age:23
}
var anotherPerson=createAnother(person);
alert(anotherPerson.name);
寄生式继承的缺点:不能做到函数复用而降低效率。
寄生组合式继承
组合继承虽然是javascript最常用的继承模式,但是他也不是完美的,这种继承的问题是不管怎么样我么都会调用俩次父对象构造函数,大家可以看之前的例子,下面这个是寄生组合式继承的例子,是最完美的继承:
function object (o)//这个o相当于父对象实例
{
function F(){}//这个F相当子对象
F.prototype=o;//继承
return new F();//实例化传出
}
function inheritPrototype(subType,superType)
{
var prototype=object(superType.prototype);//创建对象
prototype.construct=subType;//增强对象
subType.prototype=prototype;//指定对象
}
function SuperType(name)
{
this.name=name;
}
SuperType.prototype.sayName=function()
{
alert(this.name);
}
function SubType(name,age)
{
SuperType.call(this,name);
this.age=age;
}
inheritPrototype(SubType,SuperType);
SubType.prototype.sayAge=function(){
alert(this.age);
}
var person1=new SubType("Tom",23);
person1.sayName();
十一、js继承实现多态
<script type="text/javascript">
function Animal(){
this.say=function(){
alert("我是动物");
};
}
function Dog(){
this.say=function(){
alert("我是狗");
};
}
Dog.prototype=new Animal();
function Cat(){
this.say=function(){
alert("我是猫");
};
}
Cat.prototype=new Animal();
function say(animal){
if(animal instanceof Animal){
animal.say();//调用子类的方法实现多态
}
}
var dog=new Dog();
var cat=new Cat();
say(dog);
say(cat);
</script>
十二、继承顺序
先访问自己本身的方法,没有再访问自己原型的方法,本身原型没有访问父类,父类没有,访问父类的原型方法...继续往上
Object.prototype.say=function () { //最上层定义say的方法
alert("我是顶层的方法");
}
function person () {
this.say=function () {
alert("我是父类的方法");//先访问本身方法,再访问原型方法
}
}
person.prototype.say=function () {
alert("我是父类原型的方法");
}
function study () {
this.say=function () {
alert("本身的方法");
}
}
study.prototype=new person();
study.prototype.say=function () {
alert("本身原型的方法");
}
var zhangsan=new study ();
alert(zhangsan.say)//父类有方法,不再向顶层找方法
//本地对象
var arr=new Array();
var str="百度";
var str=new String();
标签:function,name,代码,js,alert,new,var,编写,prototype From: https://blog.51cto.com/u_11837698/6081917