zoukankan      html  css  js  c++  java
  • js-20170819-prototype对象

    1. 概述
    1.1 构造函数的缺点
    JavaScript 通过构造函数生成新对象,因此构造函数可以视为对象的模板。实例对象的属性和方法,可以定义在构造函数内部
    function Cat(name, color) {
    this.name = name;
    this.color = color;
    this.meow = function () {
    console.log('mew, mew, mew...');
    };
    }
     
    var cat1 = new Cat('大毛', '白色');
    var cat2 = new Cat('二毛', '黑色');
     
    cat1.meow === cat2.meow
    // false
    上面代码中,cat1和cat2是同一个构造函数的实例。但是,它们的meow方法是不一样的,就是说每新建一个实例,就会新建一个meow方法。这既没有必要,又浪费系统资源,因为所有meow方法都是同样的行为,完全应该共享。
    1.2 prototype 属性的作用
    JavaScript 的每个对象都继承另一个对象,后者称为“原型”(prototype)对象。只有null除外,它没有自己的原型对象
    原型对象上的所有属性和方法,都能被派生对象共享。这就是 JavaScript 继承机制的基本设计
    通过构造函数生成实例对象时,会自动为实例对象分配原型对象。每一个构造函数都有一个prototype属性,这个属性就是实例对象的原型对象
    当实例对象本身没有某个属性或方法的时候,它会到构造函数的prototype属性指向的对象,去寻找该属性或方法。这就是原型对象的特殊之处
    原型对象的作用,就是定义所有实例对象共享的属性和方法。这也是它被称为原型对象的原因,而实例对象可以视作从原型对象衍生出来的子对象
    1.3 原型链
    所有对象的原型最终都可以上溯到Object.prototype,即Object构造函数的prototype属性指向的那个对象。那么,Object.prototype对象有没有它的原型呢?回答可以是有的,就是没有任何属性和方法的null对象,而null对象没有自己的原型
    “原型链”的作用是,读取对象的某个属性时,JavaScript 引擎先寻找对象本身的属性,如果找不到,就到它的原型去找,如果还是找不到,就到原型的原型去找。如果直到最顶层的Object.prototype还是找不到,则返回undefined
    需要注意的是,一级级向上,在原型链寻找某个属性,对性能是有影响的。所寻找的属性在越上层的原型对象,对性能的影响越大。如果寻找某个不存在的属性,将会遍历整个原型链。
    举例来说,如果让某个函数的prototype属性指向一个数组,就意味着该函数可以当作数组的构造函数,因为它生成的实例对象都可以通过prototype属性调用数组方法
    1.4 constructor 属性
    prototype对象有一个constructor属性,默认指向prototype对象所在的构造函数。
    function P() {}
     
    P.prototype.constructor === P
    // true
    由于constructor属性定义在prototype对象上面,意味着可以被所有实例对象继承。
     
     
    2. instanceof 运算符
    instanceof运算符返回一个布尔值,表示指定对象是否为某个构造函数的实例。
    var v = new Vehicle();
    v instanceof Vehicle // true
    instanceof运算符的左边是实例对象,右边是构造函数。它会检查右边构建函数的原型对象,是否在左边对象的原型链上。因此,下面两种写法是等价的。
    v instanceof Vehicle
    // 等同于
    Vehicle.prototype.isPrototypeOf(v)
     
     
    3. Object.getPrototypeOf()
    Object.getPrototypeOf方法返回一个对象的原型。这是获取原型对象的标准方法。
    // 空对象的原型是Object.prototype
    Object.getPrototypeOf({}) === Object.prototype
    // true
     
    // 函数的原型是Function.prototype
    function f() {}
    Object.getPrototypeOf(f) === Function.prototype
    // true
     
    // f 为 F 的实例对象,则 f 的原型是 F.prototype
    var f = new F();
    Object.getPrototypeOf(f) === F.prototype
    // true
     
     
    4. Object.setPrototypeOf()
    Object.setPrototypeOf方法可以为现有对象设置原型,返回一个新对象。
    Object.setPrototypeOf方法接受两个参数,第一个是现有对象,第二个是原型对象。
    var a = {x: 1};
    var b = Object.setPrototypeOf({}, a);
    // 等同于
    // var b = {__proto__: a};
     
    b.x // 1
     
     
    5. Object.create()
    生成实例对象的常用方法,就是使用new命令,让构造函数返回一个实例。但是很多时候,只能拿到一个实例对象,它可能根本不是由构建函数生成的,那么能不能从一个实例对象,生成另一个实例对象呢?
    JavaScript 提供了Object.create方法,用来满足这种需求。该方法接受一个对象作为参数,然后以它为原型,返回一个实例对象。该实例完全继承继承原型对象的属性。
    下面三种方式生成的新对象是等价的。
    var obj1 = Object.create({});
    var obj2 = Object.create(Object.prototype);
    var obj3 = new Object();
    使用Object.create方法的时候,必须提供对象原型,即参数不能为空,或者不是对象,否则会报错。
     
     
    6. Object.prototype.isPrototypeOf()
    对象实例的isPrototypeOf方法,用来判断一个对象是否是另一个对象的原型。
    var o1 = {};
    var o2 = Object.create(o1);
    var o3 = Object.create(o2);
     
    o2.isPrototypeOf(o3) // true
    o1.isPrototypeOf(o3) // true
    上面代码表明,只要某个对象处在原型链上,isPrototypeOf都返回true。
    Object.prototype.isPrototypeOf({}) // true
    Object.prototype.isPrototypeOf([]) // true
    Object.prototype.isPrototypeOf(/xyz/) // true
    Object.prototype.isPrototypeOf(Object.create(null)) // false
    上面代码中,由于Object.prototype处于原型链的最顶端,所以对各种实例都返回true,只有继承null的对象除外
     
     
    7. Object.prototype.__proto__
    __proto__属性(前后各两个下划线)可以改写某个对象的原型对象。
     
     
    8. 获取原型对象方法的比较
    __proto__属性指向当前对象的原型对象,即构造函数的prototype属性。
     
    var obj = new Object();
    obj.__proto__ === Object.prototype
    // true
    obj.__proto__ === obj.constructor.prototype
    // true
    获取实例对象obj的原型对象,有三种方法。
    obj.__proto__
    obj.constructor.prototype
    Object.getPrototypeOf(obj)
    推荐使用第三种Object.getPrototypeOf方法,获取原型对象。
    var o = new Object();
    Object.getPrototypeOf(o) === Object.prototype
    // true
     
  • 相关阅读:
    解决绘图中闪烁的问题(C#)
    创建XML文件以及XML中的节点和更新Xml文件中的节点的值
    在C#中SendMessage和PostMessage的参数传递
    [置顶]在C#中SendMessage和PostMessage的参数传递
    C#中使用DOS命令关闭当前正在运行的程序并重新启动
    Winform中扩展Panel使之具备双缓存,防止闪屏
    用C#调用Windows API向指定窗口发送
    界面控件
    观察站模式
    利用dataview为datatable排序
  • 原文地址:https://www.cnblogs.com/jialuchun/p/7511675.html
Copyright © 2011-2022 走看看