• 类和模块


    一、类

      JavaScript中类的实现是基于原型机制的。如果两个实例都从同一个原型上继承属性,则他们它们是同一个类的实例,类的所有实例对象都从同一个原型对象上继承属性。

       使用构造函数定义类

     1 //使用构造函数定义一个范围类
     2 function Range(from,to){
     3     this.from=from;
     4     this.to=to;
     5 }
     6 Range.prototype={
     7     //定义构造器属性
     8     constructor:Range,
     9     //判断x是否在范围内
    10     include:function (x){
    11         return this.from<=x&&x<=this.to;
    12     },
    13      //对范围内的每一个整数执行f;
    14     foreach:function (f){
    15         for(var i=Math.ceil(this.from);i<=this.to;i++)
    16         {
    17             f(i);
    18         }
    19     },
    20     //返回表示范围的字符串
    21     toString(){
    22         return this.from+'...'+this.to;
    23     }  
    24 }
    25 //调用构造函数
    26 var range=new Range(1,10);
    27 console.log(range.include(5));//true
    28 range.foreach((ele)=>{console.log(ele)});//1  2  3  4 5..10
    29 console.log(range.toString());//1...10

      构造函数是类的公共表示(往往代表类明),而原型对象是类的唯一标识。

       类的实例是一个独立的对象,直接给实例定义的属性不会被所有实例共享。可以用来模拟实例字段。

       原型对象的属性和方法或被类的实例所共享,可以用来模拟类的实例方法。

       构造函数上定义的方法可以直接用构造函数对象调用,可以用来模拟类的方法(通过类名调用)

       java中用final表示声明字段为常量。JavaScript可以使用属性名字全部大写来暗示这是一个常量。

       java中可以把字段设置为私有成员(类的外部不可见)。JavaScript中使用属性名以下划线开始暗示这是一个私有变量。 

     1 //使用构造函数定义一个范围类
     2 function Range(from,to){
     3     //定义实例方法:对象字段;保存对象的独立状态
     4     this.from=from;
     5     this.to=to;
     6 }
     7     //定义实例方法:所有实例共享
     8 Range.prototype={
     9     //定义构造器属性
    10     constructor:Range,
    11     //判断x是否在范围内
    12     include:function (x){
    13         return this.from<=x&&x<=this.to;
    14     },
    15      //对范围内的每一个整数执行f;
    16     foreach:function (f){
    17         for(var i=Math.ceil(this.from);i<=this.to;i++)
    18         {
    19             f(i);
    20         }
    21     },
    22     //返回表示范围的字符串
    23     toString(){
    24         return this.from+'...'+this.to;
    25     }  
    26 }
    27 //类的方法和属性
    28 Range.NAME='Range';//大写表示只读的。
    29 Range._format="";//下划线表示它是私有变量  

    可以将上面的过程封装成一个defineClass方法。

     1 //将p对象的属性复制到o对象,覆盖同名方法
     2 //构造器属性只能复制值
     3 function extend(o, p) {
     4     for (var s in p) {
     5         if (p.hasOwnProperty(s))
     6             o[s] = p[s];
     7     }
     8     return o;
     9 }
    10 function defineClass(constructor, method, static) {
    11     //constructor代表创建类的构造函数
    12     //method  实例方法
    13     //static 类方法
    14     if (method)
    15         extend(constructor.prototype, method);
    16     if (static)
    17         extend(constructor, static);
    18     return constructor;
    19 }
    20 //定义一个SimpleRange
    21 var SimpleRange = defineClass(function () { this.x = 1; this.y = 2 },
    22     { add: function () { return 10 } },
    23     { pi: 3.14 });
    24 var s=new SimpleRange();
    25 console.log(SimpleRange.pi)//3,14
    26 console.log(s.x);//1
    27 console.log(s.add());//10

    二、类的扩充

      JavaScript基于原型的继承是动态的,给对象的原型添加的方法,继承这个原型对象也会继承这些方法。   

    1 Pange.prototype.toJson=function(){
    2     return ....//
    3 }

      类的实例对象都会添加toJson();

      我们可以内置对象的原型上添加方法,是内置对象都可以使用这个方法。

    三、检测对象类的方法 

       intanceof、对象的constructor属性、isprototype()    

    1 var o={};
    2 console.log(o instanceof Object);//true
    3 console.log(Object.prototype.isPrototypeOf(o));//true
    4 console.log(o.constructor);//Object函数的引用

      intanceof和constructor属性会在web应用存在问题,web的框架和多窗中会有独立的上限下文,独立上下文包含独立的变量和构造方法。一个框架页面中的数组不是另一个框架页面中Array()的实例,所以instance和constructor返回false;

    四. 面向对象技术

    定义一个集合类Set

     1 //定义集合类 :将传入的值建立一个唯一的到字符串的映射,然后将字符串和值保存进对象中
     2 
     3 //定义一个构造函数
     4 function Set() {
     5     //用于将值保存在对象中
     6     this.value = {};
     7     //集合中值得个数
     8     this.n = 0;
     9     //初始化集合中的值。
    10     this.add.apply(this, arguments);
    11 }
    12 //定义一个类内部使用的私有属性;用来产生值对应的字符串
    13 Set._v2s = function (val) {
    14     switch (val) {
    15         case undefined: return "u";
    16         case null: return 'n';
    17         case true: return 't';
    18         case false: return 'f';
    19         default: switch (typeof val) {
    20             case "number": return "#" + val;
    21             case "string": return '"' + val;
    22             default: return "@" + objectid(val);
    23         }
    24     }
    25 }
    26 //生成对象的id方法
    27 function objectid(val) {
    28     //相同的对象产生相同的id,不同的对象产生不同的id
    29     var prop = "|*prop*|";//定义一个私有属性
    30     if (!val.hasOwnProperty(prop))
    31         val[prop] = Set._v2s.next++;
    32     return val[prop];
    33 }
    34 //定义一个类属性
    35 Set._v2s.next = 100;
    36 //给集合添加实例方法
    37 Set.prototype.add = function () {
    38     for (var i = 0; i < arguments.length; i++) {
    39         var val = arguments[i];
    40         //得到值到字符串的映射
    41         var str = Set._v2s(val);
    42         //检验集合中是否存在这个字符串
    43         if (!this.value.hasOwnProperty(str)) {
    44             //当集合中不存在这个值时,将值保存近集合
    45             this.value[str] = val;
    46             this.n++;
    47         }
    48     }
    49     return this;//支持链式编程
    50 }
    51 //删除集合中的值
    52 Set.prototype.remove = function () {
    53     for (var i = 0; i < arguments.length; i++) {
    54         var val = arguments[i];
    55         //得到值到字符串的映射
    56         var str = Set._v2s(val);
    57         //检验集合中是否存在这个字符串
    58         if (this.value.hasOwnProperty(str)) {
    59             //当集合中存在这个值时,将值删除
    60             delete this.value[str]
    61             this.n--;
    62         }
    63     }
    64     return this;//支持链式编程
    65 }
    66 //判断集合中是否有这个值
    67 Set.prototype.contains = function (val) {
    68     var str = Set._v2s(val);
    69     return val.hasOwnProperty(str);
    70 }
    71 //遍历集合,使用指定的上下文执行f函数
    72 Set.prototype.forEach=function(f,content){
    73    for(var p in this.value){
    74        if(this.value.hasOwnProperty(p)){
    75            f.call(content,this.value[p]);
    76        }
    77    }
    78    return this;
    79 }
    80 //返回集合的大小
    81 Set.prototype.size=function(){
    82     return this.n;
    83 }
    84 //创建一个集合
    85 var set=new Set(1,2,3);
    86 set.add(4,5,6,{},{},{x:1});
    87 set.remove(4,5);
    88 set.forEach((ele)=>{console.log(ele)});
    89 console.log(set.size());
    90 console.log(set.contains(1));

    五、标准转化方法

      应该给类的原型上定义一些标准转发方法:toString()、valueOf()、toJSON()、toLocalString()。这些方法在对象的类型转换时会用到。如果没有定义最好是刻意为之而不是忘了定义。

      对象的比较是引用的比较,我们可以自己在原型定义一类比较方法。

    六、方法借用

      多个类中的方法可以共用一个函数,我们称之为方法借用。

      如;Set.prototype.equals=A.equals;

    七、可以利用闭包实现变量的私有 

     1 //变量只能被类的实例方法访问,类的外面不可见
     2 function Range(from,to){
     3     this.from=function(){
     4         return from;
     5     }
     6     this.to=function(){
     7         return to;
     8     }
     9 }
    10 Range.prototype.include=function(x){
    11     return this.from()<=x&&x<=this.to;
    12 }

    八、构造方法的重载和工厂方法

      有时候,我们希望对象的初始化有多种方式,比如我们用构造函数创建初始化一个数组。

      

      

      

     

      

      

      

  • 相关阅读:
    【转】 web前端基础知识-(五)jQuery
    【转】 web前端基础知识-(四)DOM
    【转】 web前端基础知识-(三)JavaScript基本操作
    【转】 web前端基础知识-(二)CSS基本操作
    【转】 web前端基础知识-(一)html基本操作
    Vue的dom更新机制 & Vue的nextTick
    VUE项目中实现PDF预览
    WebView
    Nginx服务器
    前端存储 --- cookie & localStorage & sessionStorage & Web SQL & IndexDB & Cache Storage
  • 原文地址:https://www.cnblogs.com/yiluhuakai/p/8586819.html
Copyright © 2020-2023  润新知