js的继承的实现与代码编写

2023-11-11

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();

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

js的继承的实现与代码编写 的相关文章

  • linux kerne新版本编号?

    今天看到linux内核版本号都到3 4了 心中非常惊讶 为什么现在版本飞这么快了 于是一番google 终于找到了两篇文章 大家可以看看 Linux kernel version bumped up to 3 0 as 20th birth
  • VirtualBox 安装 增强功能

    在VirtualBox中安装好系统后 一般建议安装增强功能 因为一开始左上方的 视图 菜单中无缝模式和自动调整显示尺寸功能不可用 屏幕分辨率不够 无法与原系统共享剪贴板等 安装过程如下 点击VirtualBox的 设备 安装增强功能 此时桌
  • 解决 PHP Mysql 和 UTF8的问题

    http sixpoint me 443 solving php mysql utf8 issue 1 数据库 CREATE DATABASE db name CHARACTER SET utf8 DEFAULT CHARACTER SET
  • 【vue】页面缓存回跳后 侧边栏z-index层级导致页面快闪

    问题描述 公司使用的帆软报表页面没有加keepAlive缓存 在从一个弹框页面跳转到子报表后 切换路由回到当前页面是会继续展示弹框页面 但是页面由于z index层级问题会闪一下 问题排查 经过代码查看是因为导航栏小箭头使用了定位 z in
  • vue 的酒店⺠宿⽹站毕业设计源码250910

    基于Springboot的酒店民宿网站 摘 要 随着互联网和宽带上网的普及 Internet 网站在中国异军突起 并日益渗透到人们的日常生活中 网站是运用现代通信技术 计算机和网络技术进行的一种社会形态 其目的是通过互联网满足人们的需求 在

随机推荐

  • sql查询条件:闭区间和开区间(>=和>)效率分析

    A select from T Info Passengers where id gt 3245B select from T Info Passengers where id gt 3245 A 返回结果46956条 占用时间 毫秒 读取
  • bigdecimal加减乘除运算

    1 加法 Test public void testAdd 用double类型初始化BigDecimal对象 BigDecimal numA new BigDecimal 0 05 BigDecimal numB new BigDecima
  • 【数据结构】排序算法大总结

    文章目录 1 排序的概念及运用 2 常见排序算法的实现 2 1 插入排序 2 1 1 直接插入排序 2 1 2 希尔排序 2 2 选择排序 2 2 1 直接选择排序 2 2 2 堆排序 2 3 交换排序 2 3 1 冒泡排序 2 3 1 快
  • 图解redis五种数据结构底层实现(动图版)

    redis有五种基本数据结构 字符串 hash set zset list 但是你知道构成这五种结构的底层数据结构是怎样的吗 今天我们来花费五分钟的时间了解一下 目前redis版本为3 0 6 动态字符串SDS SDS是 simple dy
  • Spring Cloud Gateway网关工作原理、网关谓词和GatewayFilter工厂

    Spring Cloud Gateway 官方文档地址 https docs spring io spring cloud gateway docs current reference html Spring Cloud Gateway项目
  • 2021-01-25

    1 运算符优先级 2 条件判断 2 1 条件判断语句 if语句 执行的流程 if语句在执行时 会先对条件表达式进行求值判断 如果为True 则执行if后的语句 如果为False 则不执行 语法 代码块中保存着一组代码 同一个代码块中的代码
  • Sample Python Implementation using a Linked List

    直接贴代码 class Node object def init self value next node None self value value self next node next node class List object d
  • Netlist与RTL仿真结果不匹配

    Netlist 仿真和RTL比匹配主要是因为Netlist会存在不定态以及传播不定态 导致仿真不正确 不定态的来源 大多数设计在上电时不能保证cell的特定的逻辑状态 flip flop或memory根据环境因素 芯片间的工艺差异等可能会有
  • nacos访问地址无登录界面问题:版本2.2.3

    场景 访问 localhost 8848 nacos 地址时 没有弹出登录界面 提示 当前集群没有开启鉴权 请参考文档开启鉴权 此时左边菜单也没有权限控制模块 原因分析 这是新版本的配置文件中鉴权开关没有开启的原因 具体可以修改以下配置项
  • python-使用chinese_calendar判断是否节假日/工作日/调休日,-使用weekday()判断星期几

    最近在编写一个小程序时 需要判断是否为工作日 节假日以及星期几 发现chinese calendar这个第三方插件还蛮好用 可以用来识别是否工作日 datetime下的weekday 判断星期几 现做如下分享 一 工作日 节假日的判断 1
  • 区块链技术学习笔记——1.区块链介绍

    基本概念 区块链介绍 区块链是一个由多个参与方共同维护的并且持续增长的分布式数据库 通常也被称作分布式共享账本 可以促进在业务网络中记录交易和跟踪资产的过程 把多笔交易的信息以及表明该区块的信息打包放在一起 经验证后的这个包就是区块 每个区
  • vue常用插件集合

    vue常用插件集合 vue treeselect vue treeselect 是一个多选组件 具有对 Vue js嵌套选项支持 vue layer使用方法 官网 可拖动对话框 支持传入组件 element表单自动生成 Element Pl
  • Go结构体

    struct类型是值类型 Go语言没有class类型 只有struct类型 定义 var stu Student var stu Student new Student var stu Student Student golang中的str
  • 码农保命秘诀之全身检查_专属全身体检项目大全

    废话不多说 狗命要紧 下面直接上干货 健康活着才有输出 特别是28 35之间的不注重身体 往往打败你的不是敌人 而是你自己 还怎么冲刺35大关 里面的注释简单看看就行 主要是照单让医生开单检查 挂个内科 说自己身体哪里不舒服 需要这些检查
  • ADS系列 – 低噪声放大器(LNA)模型下载安装及 LNA仿真设计

    1 概述 低噪声放大器 Low Noise Amplifier LNA 作为接收系统的第一个电路单元 它的性能直接影响着整个接收机的性能 低噪声放大器的功能是在保证产生最低的噪声前提下 将信号进行放大 以降低后续模块所产生的噪声对信号的影响
  • windows2008 不能跳出修复选项

    windows2008 R2意外断电后无法启动 提示修复或者正常启动 但即便你选择正常启动 系统还是会跳到修复选项 看起来是要折腾一下 BIOS自检 找到硬盘引导记录MBR MBR读分区表 找到主分区 读取主分区的引导记录 搜索启动管理器文
  • 三、C++语言进阶:动态库与静态库之类篇

    3 动态库与静态库之类篇 3 1 素材 文件 test h pragma once class Test public Test Test void Func int i test cpp include
  • 【死磕 Java 基础】— 我同事一个 select 分页语句查出来了 3000W 条数据

    大家好 我是大明哥 某天我正在工位上听着 Victory 愉快地敲着 hello world 这感觉就像我写的代码能征服世界 突然运维给我打了一个电话 说我们某台服务器 OOM 了 要我过去看下 这感觉就像 xxx 你懂的 去运维室 登录服
  • 【HBZ分享】ElasticSearch读写数据的原理 以及 路由策略原理-【短而精悍,易于理解】

    ElasticSearch分布式工作原理 是如何进行读写数据的 1 简单介绍ES 首先es是分布式的 只要我们启动相应数量的节点 并且这些节点分配相同的cluster name 那他们就对属于同一个集群了 创建索引的时候 只需要指定对应的主
  • js的继承的实现与代码编写

    js的继承的实现与代码编写 一 继承 对象的一个类可以从现有的类中派生 并且拥有现有的类的方法或是属性 这和过程叫做继承 被继承的类叫做父类或是基类 继承的类叫做子类 一个对象拥有另一个对象的属性和方法 在 JavaScript 中 是没有