js复习笔记--类(三)

类和模块

1. 类和原型
  • 利用工厂函数创建范围类初始化实例:
    function range(from, to){
        var r = Object.create(range.methods);
        r.from = from;
        r.to = to;
        return r;
    }

    //左闭右开
    range.methods = {
        includes: function(x){
            return x >= this.from && x < this.to;
        },
        foreach: function(f){
            for(var x = Math.ceil(this.from); X < this.to; x++) 
                f(x);
        },
        toString: function(){
            return "(" + this.from + "..." + this.to + ")";
        }
    };

    var r = range(1, 3); // => 返回一个对象
    r.includes(2); // => true
    r.foreach(console.log); // => 1, 2
    console.log(r); // => (1...3)
2. 类和构造函数
  • 利用构造函数定义范围类:
    function Range(from, to){
        this.from = from;
        this.to = to;
    }

    //左闭右开
    Range.prototype = {
        includes: function(x){
            return x >= this.from && x < this.to;
        },
        foreach: function(f){
            for(var x = Math.ceil(this.from); X < this.to; x++) 
                f(x);
        },
        toString: function(){
            return "(" + this.from + "..." + this.to + ")";
        }
    };

    var r = new Range(1, 3); // => 返回一个对象
    r.includes(2); // => true
    r.foreach(console.log); // => 1, 2
    console.log(r); // => (1...3)
  • 类的标识:
    如上:r instanceof Range // 如果r继承自Range.prototype则返回true
    instanceof 不会检查r是否由Range()构造函数初始化,而是检查其proto是否是Range.prototype(即是否继承自Range.prototype)

  • constructor:
    每个js函数拥有一个prototype属性,该属性值是一个对象,对象中包含一个不可枚举属性constructor,该属性的值是一个函数对象,即该函数本身的定义:

    var F = function(){};
    var p = F.prototype;
    var cons = p.constructor;
    cons === F; // => true
    构造函数           原型                   实例
    |Range() |<-----| 构造函数|    继承
    |        |      | includes| <-------- new Range(1, 2)
    | 原型   |----->| foreach |

由于我们显示定义了Range的prototype,因此应该显示指定constructor:

    Range.prototype = {
        constructor: Range,
        includes: function(x){
            return x >= this.from && x < this.to;
        },
        foreach: function(f){
            for(var x = Math.ceil(this.from); X < this.to; x++) 
                f(x);
        },
        toString: function(){
            return "(" + this.from + "..." + this.to + ")";
        }
    };
3. prototype与proto:
  • 几乎所有的函数(除了一些内建函数)都有一个名为prototype(原型)的属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以有特定类型的所有实例共享的属性和方法。prototype是通过调用构造函数而创建的那个对象实例的原型对象。hasOwnProperty()判断指定属性是否为自有属性;in操作符对原型属性和自有属性都返回true。
    var obj = {a: 1};
    obj.hasOwnProperty("a"); // true
    obj.hasOwnProperty("toString"); // false
    "a" in obj; // true
    "toString" in obj; // true
  • 对象具有属性proto,可称为隐式原型,一个对象的隐式原型指向构造该对象的构造函数的原型,这也保证了实例能够访问在构造函数原型中定义的属性和方法。
    function Foo(){}
    var Boo = {name: "Boo"};
    Foo.prototype = Boo;
    var f = new Foo();

    console.log(f.__proto__ === Foo.prototype); // true
    console.log(f.__proto__ === Boo);   // true
    Object.getPrototypeOf(f) === f.__proto__;   // true

即一个由new获取的对象, 其proto隐藏属性的值, 是其构造函数的prototype属性值对应的对象。

4. 定义子类:
  • 方法:例如定义A的子类B
    B.prototype = Object.create(A.prototype);
    B.prototype.constructor = B
  • 一个巧妙的方式定义工厂函数+构造函数
function Range(from, to){
    var prop = {
        from: {value: from, enumerable: true, writable: false, configurable: false},
        to: {value: to, enumerable: true, writable: false, configurable: false}
    };

    if (this instanceof Range) //判断是否为构造函数调用
        Object.defineProperties(this, prop);
    else //函数调用
        return Object.create(Range.prototype, prop);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值