当前位置: 首页 > news >正文

JS实现OO机制

一、简单原型机制介绍

继承是OO语言的标配,基本所有的语言都有继承的功能,使用继承方便对象的一些属性和方法的共享,Javascript也从其他OO语言上借鉴了这种思想,当一个函数通过"new"创建出一个实例后,那么这个实例就拥有这个函数的prototype对象所有的属性和方法,从而实现所有的实例都能共享一组实例和方法,Javascript所谓的类就行通过修改这个prototype对象实现的,以区别其他的原生对象,及自定义类

<script>
    function A(){}
    A.prototype={
        a:"a",
        fun:function () {}
    }
    var a=new A();
    var b=new A();
    alert(a.a===b.a);//true
    alert(a.fun===b.fun)//true
</script>

总结:

1、我们将定义在原型上的方法(属性)叫做原型方法,原型方法(属性)被所有的实例所共享

2、但是我们不能加所有的属性和方法都定义到原型上,JS为了实现差异化,允许我们将方法和属性定义到构造函数内部,这叫做特权方法(属性)。

3、因此我们把共享的属性和方法放到原型内,把私有的数据放到构造函数里面。

    function A() {
        var count=0;
        this.a=1;
        this.fun=function () {
            
        }
    }
    A.prototype={
        b:1,
        fun1:function () {}
    }
    var a=new A();
    var b=new A();
    alert(a.a);//输出1
    alert(a.count);//输出undefined

4、当我们把方法和属性定义于this上面,那么外界还是能访问到,所以当方法(属性)是特有属性(方法),那么别置于this之下,之间定义到构造函数内部,并用var修饰,这是它就是名副其实的私有属性。

    function A(){
        var count=1;
        this.a=666;
        this.fun=function () {
            
        }
    }
    A.prototype={
        a:"aaa",
        b:666666,
        fun:function () {
        }
    }
    var a=new A();
    var b=new A();
    alert(a.a===b.a);//输出:true  因为a是基本类型所以比较值
    alert(a.fun===b.fun);//输出:false  比较引用
    alert(a.a);//输出:666  说明特权属性会覆盖原型属性,当两个属性名一样的时候
    delete a.a;
    alert(a.a);//输出:aaa   删除特权属性后,输出原型属性

 

5、特权方法(属性)只是遮住原型方法(属性),只要使用delete 删除,就又能访问到原型属性

 

二、OO静态方法实现

<script>
    function A(){}
    A.a=function () {
        alert(1);
    }
    A.a();//输出:1;
</script>

 

三、OO继承的实现

上面介绍了原型模式的用法,我们给prototype定义了什么方法和属性,那么对应的实例就会共享prototype中的方法和属性,那么当我们将A对象的prototype属性赋给B对象时,那么B对象就拥有了所有的A对象中原型中的属性和方法。

    function A(){}
    A.prototype={
        a:666
    }
    function B(){}
    B.prototype=A.prototype;
    var b=new B();
    alert(b.a);//输出:666

由于引用着同一个对象,这意味着,我们修改A对象的原型,那么B对象的原型也会受到影响,因此我们不能把同一个对象赋给两个类,所以这个问题需要解决

方法一:通过for in把父类的原型属性和方法一一的赋给子类的原型

    //通过继承拷贝来实现继承,缺点是无法通过instanceof来判断实例类型
    function extend(destination,source){
        for(var prototype in source){
            destination[prototype]=source[prototype];
        }
        return destination;
    }

    function A(){}
    A.prototype={
        a:666
    }
    function B(){}
    var b=extend(A,new A());
    alert(b.a);//输出:666

 

方法二:子类的原型不从父类的原型那里直接获得,而是通过一个中间函数,将父类的原型赋值给该函数,然后这个函数的实例作为子类的原型

    /**
     * 解决通过prototype赋值型继承的应用同一个对象的问题
     * @constructor
     */

    //通过中间函数来解决
    function A(){}
    A.prototype={
        a:666
    }
    function Bridge(){}
    Bridge.prototype=A.prototype;

    function B(){}
    B.prototype=new Bridge();

    var a=new A();
    var b=new B();
    alert(A.prototype==B.prototype);//说明他们的原型被分开
    alert(a.a===b.a);//输出:true  子类共享父类的原型属性(方法)
    //为父类动态添加方法
    A.prototype.lala=function(){
        alert(1);
    }
    b.lala();//输出:1  子类获得了这个方法

    B.prototype.lele=function () {
        alert(2);
    }
    //a.lele();//error  父类不具有子类的方法

    alert(b instanceof A);//true
    alert(b instanceof B);//true

方法二:能通过instanceof的验证,现在es5就自带了这种方法来实现原型继承。这种方法还有另外一种简介的实现Object.Creat

<script>
    /**
     * 继承2的简洁版,通过一个方法来实现继承
     * @param o  父类的原型
     * @returns {F}  中间函数的原型
     */
    Object.create=function (o) {
        function F() {}
        F.prototype=o;
        return new F();
    }
</script>

 

相关文章:

  • Sql Server数据批量更新
  • Linux usb子系统(一) _写一个usb鼠标驱动
  • SylixOS iMX6平台I2C总线驱动
  • HTML初学者常用标签及属性
  • jquery特效 商品SKU属性规格选择实时联动
  • centos
  • Greenplum 简单性能测试与分析
  • 智障的对话
  • 一维数组打乱顺序shuffle函数
  • seajs
  • 完成数据的打通-豌豆荚被阿里巴巴收购后的168天
  • 神奇的模块--谷歌开源 Python Fire:自动生成命令行接口
  • PHP快速入门 如何操作MySQL
  • 【Java基础】5、java中的匿名内部类
  • Android textview及其子类
  • [iOS]Core Data浅析一 -- 启用Core Data
  • __proto__ 和 prototype的关系
  • 【402天】跃迁之路——程序员高效学习方法论探索系列(实验阶段159-2018.03.14)...
  • 【剑指offer】让抽象问题具体化
  • 30秒的PHP代码片段(1)数组 - Array
  • bootstrap创建登录注册页面
  • docker-consul
  • java第三方包学习之lombok
  • mysql 5.6 原生Online DDL解析
  • Storybook 5.0正式发布:有史以来变化最大的版本\n
  • Vue.js 移动端适配之 vw 解决方案
  • 前端性能优化--懒加载和预加载
  • 提升用户体验的利器——使用Vue-Occupy实现占位效果
  • 学习使用ExpressJS 4.0中的新Router
  • 一个项目push到多个远程Git仓库
  • 运行时添加log4j2的appender
  • Nginx实现动静分离
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • #android不同版本废弃api,新api。
  • #我与虚拟机的故事#连载20:周志明虚拟机第 3 版:到底值不值得买?
  • $().each和$.each的区别
  • $.ajax,axios,fetch三种ajax请求的区别
  • (1/2)敏捷实践指南 Agile Practice Guide ([美] Project Management institute 著)
  • (175)FPGA门控时钟技术
  • (附源码)ssm码农论坛 毕业设计 231126
  • (附源码)计算机毕业设计SSM疫情下的学生出入管理系统
  • (利用IDEA+Maven)定制属于自己的jar包
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (四)linux文件内容查看
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • ***测试-HTTP方法
  • ./include/caffe/util/cudnn.hpp: In function ‘const char* cudnnGetErrorString(cudnnStatus_t)’: ./incl
  • .Net IE10 _doPostBack 未定义
  • .netcore 如何获取系统中所有session_如何把百度推广中获取的线索(基木鱼,电话,百度商桥等)同步到企业微信或者企业CRM等企业营销系统中...
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比
  • .NET应用架构设计:原则、模式与实践 目录预览
  • .sh
  • .w文件怎么转成html文件,使用pandoc进行Word与Markdown文件转化
  • @javax.ws.rs Webservice注解
  • @JsonSerialize注解的使用