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
     
  • 相关阅读:
    Java实现 蓝桥杯VIP 算法提高 排队打水问题
    Java实现 蓝桥杯VIP 算法提高 排队打水问题
    Java实现 蓝桥杯VIP 算法提高 排队打水问题
    Java实现 蓝桥杯VIP 算法提高 特殊的质数肋骨
    Java实现 蓝桥杯VIP 算法提高 特殊的质数肋骨
    Java实现 蓝桥杯VIP 算法提高 特殊的质数肋骨
    Java实现 蓝桥杯VIP 算法提高 特殊的质数肋骨
    现在使用控件, 更喜欢继承(覆盖控件已有的函数,很奇怪的一种使用方式)
    Controls 属性与继承 TShape 类的小练习(使用TShape可以解决很多图形问题)
    QT创建窗口程序、消息循环和WinMain函数(为主线程建立了一个QEventLoop,并执行exec函数)
  • 原文地址:https://www.cnblogs.com/jialuchun/p/7511675.html
Copyright © 2011-2022 走看看