zoukankan      html  css  js  c++  java
  • JavaScript学习笔记-实例详解-类(一)

    实例详解-类(一):
    //每个javascript函数(除了bind())都自动拥有一个prototype对象
    // 在未添加属性或重写prototype对象之前,它只包含唯一一个不可枚举属性constructor
    // constructor的值是一个函数对象,指代函数对象自身(构造函数)
    //原型对象是类的'唯一标识',而构造函数是类的'公共标识',因此这个constructor属性为对象提供了类
    function Range(from,to){
    this.from = from||0;
    this.to = to||0;
    }
    console.log(Range.prototype.constructor); //[Function: Range] //未重写原型之前,它的constructor指代它自身
    //==第一种方式:重写Range的原型对象prototype,若没有指定constructor属性,那么类将采用原型对象的默认原型Object类的constructor
    Range.prototype = {
    //====constructor:Range; //可以显式的给原型添加一个constructor构造函数,这里反向引用自身的构造函数
    includes: function(x){return this.from<=x && x<=this.to;},
    foreach: function(f){
    for(var x = Math.ceil(this.from);x<=this.to;x++) f(x);
    },
    toString: function(){return '('+this.from+'...'+to+')';}
    };
    /*==第二种方式:除了显式的添加constructor,还可以使用预定义原型对象,它包含属性consturctor,然后逐个的给原型添加自定义的属性:
    Range.prototype.includes = function(){...};
    Range.prototype.foreach = function(){...};
    Range.prototype.toString = functon(){...};
    */
    var r = new Range(2,4);
    console.log(r.constructor); //[Function: Object]
    console.log(r.constructor === Object); //true

    //====这里的类F1和上面的类Range比较,
    var F1 = function(){};
    var p = {constructor:F1,a:1,b:2,c:function(){}}; //显式指定对象p的构造函数constructor为F1,若未指定则p.constructor===Object;
    F1.prototype = p;
    var p2 = new F1();
    console.log(p2.constructor === p.constructor); //true 对象p2是类F1的实例,类F1重写了它的原型为对象p,所以对象p2继承了对象p的constructor;
    console.log(p2.constructor === F1); //true
    //====
    var F2 = function(){};
    //F2.sum = function(x,y){return x+y;}; //无效,不能直接为方法添加属性,只能通过它的原型对象为它添加属性
    F2.prototype.sum = function(x,y){return x+y;};
    var o = new F2();
    console.log(o.constructor === F2); //true 因为F2使用自身的默认原型,它的constructor属性(构造函数)就是指代F2自身;
    console.log(o.sum(1,2)); //3
    //==========创建一个定义类的函数defineClass(函数式编程风格)=========================
    function extend(o,p){ //定义一个复制对象属性的函数
    for(var x in p){
    o[x] = p[x];
    }
    return o;
    }
    function defineClass(constructor,methods,statics){ //该函数接收3个对象参数
    if(methods) extend(constructor.prototype,methods); //添加所有实例属性
    if(statics) extend(constructor,statics); //添加所有类属性
    return constructor; //最后要返回构造函数
    }
    var Range1 = defineClass(
    function(f,t){this.f=f;this.t=t;},
    {
    includes:function(x){return this.f<=x&&x<=this.t;},
    toString:function(){return this.f+'...'+this.t;}
    },
    {
    upto:function(t){return new Range1(0,t);}
    }
    );
    var r3 = new Range1(5,7);
    r3.includes(6);
    console.log(r3.toString());
    //==普通方法创建一个类:(调用时首先查找实例中是否直接定义了这个属性,有则返回实例属性;如果实例属性中没有就去构造函数中查找,有则返回;如果前面两者都没有就去原型对象中查找,如果没有则返回undefined)
    //1.构造函数,定义对象属性
    var Range2 = function(x,y){
    if(isNaN(x)||isNaN(y)) throw new TypeError('not a number');
    var self = this;
    this.r = x;
    this.i = y;
    };
    //2.原型属性(实例共享的属性、方法,通过实例对象来调用),也可将原型属性写进构造函数内动态的添加,但没创建一个实例就会执行一次,需要加判断是否已经创建;
    Range2.prototype.add = function(that){return new Range2(this.r+that.r,this.i+that.i);};
    Range2.prototype.mul = function(that){return new Range2(this.r*that.r,this.i*that.i);};
    Range2.prototype.mag = function(){return Math.sqrt(this.r*this.r + this.i*this.i);};
    Range2.prototype.neg = function(){return new Range2(-this.r,-this.i);};
    Range2.prototype.toString = function(){return '{'+this.r+','+this.i+'}';};
    Range2.prototype.equals = function(that){
    return that != null &&
    that.constructor === Range2 &&
    this.r === that.r &&
    this.i === that.i;
    };
    //3.类属性,方法(通过类直接调用)
    Range2.ZERO = new Range2(0,0);
    Range2.ONE = new Range2(1,0);
    Range2.I = new Range2(0,1);
    Range2._format = /^{([^,] +),([^}] +)}$/;
    Range2.parse = function(s){
    try{
    var m = Range2._format.exec(s);
    return new Range2(parseFloat(m[1],parseFloat(m[2])));
    }catch(x){
    throw new TypeError("can not parse");
    }
    };
    //4.创建实例
    var c = new Range2(2,3);
    var d = new Range2(c.i, c.r);
    //==可以随时为类(包括内置类)的原型扩展或更改属性,类的所有实例对象将随之改变==
    Range2.prototype.divide = function(){return this.r-this.i;};
    var str = c.add(d).toString();
    console.log(Range2.ONE); //{ r: 1, i: 0 }
    console.log(str); //{5,5}
    //Range2.parse(c.toString()).add(c.neg()).equals(Range2.ZERO); //函数返回自身,可实现链式调用
    //=========检测对象的类==========
    //(一)o instanceof p 检测对象o是不是p得实例 ,
    // (二) p.isPrototypeOf(o)检测p是不是o的原型,
    // (三)有constructor的函数可通过他来判断属于哪个类
    // 他们只能检测对象是否属于指定的类,而无法通过对象获得类名
    //在客户端JS中,每个窗口/框架子页面都具有单独的执行上下文,每个上下文都包含独立的全局变量和一组独立的构造函数
    // 他们之间的实例即使继承自相同的原型对象,但也是相互独立的原型对象,他们之间互不为实例
    function typeAndValue(x){
    if(x == null)return ''; //Null,undefined类型没有构造函数
    switch (x.constructor){
    case Number:return 'Number: '+x;
    case String:return 'String: '+x;
    case Date: return 'Date: ' +x;
    case RegExp:return 'RegExp: '+x;
    case Range2:return 'Renge2: '+x; //处理自定义类型
    }
    }
    //(四)通过构造函数名字来识别对象的类(但并不是所有对象都有构造函数,并不是所有函数有名字)
    function classof(o){
    return Object.prototype.toString.call(o).slice(8,-1); //获取类名
    }
    Function.prototype.getName = function(){ //返回函数名字,可能为空,非函数返回null
    if('name' in this) return this.name;
    return this.name = this.toString().match(/functions*([^(] *)(/)[1];
    };
    function type(o){
    var t, c,n;
    if(o === null)return 'null'; //处理null值
    if(o !== o ) return 'nan'; //处理NaN
    if((t = typeof o) !== 'object') return t; //typeof可以辨认除了object之外的类型
    if((c = classof(o)) !== 'Object') return c;//识别出大部分内置对象的类名,排除值为'Object'
    if(o.constructor && typeof o.constructor === 'function' && //若构造函数名字存在则返回它
    (n = o.constructor.getName())) return n;
    return 'Object'; //其它无法判别的一律返回'Object'
    }
    //=========鸭式辩型:不需要特意去检测它是什么类,只检测它是否具备我们所需要的特性就行!
    // "把会游泳,会嘎嘎叫的鸟都当着是鸭子对待!"
  • 相关阅读:
    用leangoo看板工具实施多团队大规模敏捷开发
    单团队的Scrum敏捷开发-leangoo
    放弃在每日站会上按成员逐个发言
    Leangoo思维导图做OKR目标管理
    好用的思维导图软件(程序员必备)
    好用免费的思维导图工具,多人协作共同编辑
    什么是Scrum燃尽图?
    Scrum中文网-团队需要Scrum Master做这六件事
    项目管理工具Leangoo自定义字段的应用
    实施敏捷开发中,选择看板管理工具的几个要点
  • 原文地址:https://www.cnblogs.com/susufufu/p/5705781.html
Copyright © 2011-2022 走看看