• 「JavaScript面向对象编程指南」原型


    在 JS 中,函数本身也是一个包含了方法(如apply和call)和属性(如length和constructor)的对象,而prototype也是函数对象的一个属性
    function f(){}
    f.constructor //function Function(){[native code]}
    可为prototype对象赋予属性和方法,只有当f作为构造器使用时,这些属性才会起作用

    添加属性和方法除了在构造函数中,还可通过prototype属性来增加该构造器所能提供的功能

    function Snake(name){
    	this.name = name;
    	this.eat = function(){}
    }
    Snake.prototype.color = 'grey';
    Snake.prototype.sleep = function(){}
    

    若不想逐一添加,也可定义一个对象,然后将其覆盖到之前原型上

    Snake.prototype = {
    	color:'grey';
    	sleep:function(){}
    }
    

    在 JS 中,几乎所有对象都是通过传引用的方式来传递的,因此所创建的每个新对象实体中并没
    有一份属于自己原型副本。这也就意味着可随时修改 prototype 属性,并且由同
    一构造器创建的所有对象的 prototype 属性也都会同时改变(甚至还会影响在修改之前
    就已经创建了的那些对象)

    访问某个属性时,JS引擎会遍历该对象的所有属性,找到则立即返回,找不到则会去创建当前对象的构造器函数的原型里找

    每个对象都会有一个构造器,而原型本身也是一个对象,这意味着它必然也有一个构造器,而这个构造器又会有自己的
    原型。于是这种结构可能会一直不断地持续下去,并最终取决于原型链(prototype chain)的长度,但其最后一环肯定是 Object 内建对象,因为它是最高级的父级对象。

    使用hasOwnProperty()方法可判断某属性是对象自身属性还是原型属性,返回布尔类型,false为原型属性

    对象中不是所有的属性都会在 for-in 循环中显示,如(数组的)length 属性和
    constructor 属性就不会被显示,那些会显示的属性被称枚举属性,可以通过各个对象所提供的 propertyIsEnumerable()方法来判断对象的某
    个属性是否可枚举,在 ES5 中,可以具体指定哪些属性可枚举,而在 ES3 中没有这个功能
    for-in中原型链中的各个原型属性也会被显示出来,当然前提是它们是可枚举的
    对于所有的原型属性,propertyIsEnumerable()都会返回 false,包括那些在 for-in 循环中可枚举的属性

    function Gadget(name, color) {
    	this.name = name;
    	this.color = color;
    	this.getName = function(){
    		return this.name;
    	};
    }
    Gadget.prototype.price = 100;
    Gadget.prototype.rating = 3;
    
    var newtoy = new Gadget('webcam','black');
    
    for(var k in newtoy){
    	if(newtoy.hasOwnProperty(k)){
    		console.log(k + '=' + newtoy[k]); //打印自身的可枚举属性
    	}
    }
    
    newtoy.propertyIsEnumerable('name'); //true
    
    //而对于内建属性和方法来说,它们大部分都是不可枚举的:
    newtoy.propertyIsEnumerable('constructor'); //false
    
    //另外,任何来自原型链中的属性也是不可枚举的:
    newtoy.propertyIsEnumerable('price'); //false
    
    //但是需要注意的是,如果 propertyIsEnumerable()的调用是来自原型链上的某个对象,那么该对象中的属性是可枚举的
    newtoy.constructor.prototype.propertyIsEnumerable('price'); //true
    
    

    每个对象都有个isPrototypeOf()方法,用以判断当前对象是否是另一个对象的原型

    var monkey = { name:'Sam' };
    function Human(){};
    Human.prototype = monkey;
    
    var george = new Human();
    
    //monkey是george的原型吗?
    monkey.isPrototypeOf(george); //true
    

    大多数浏览器可得到某个对象的原型,因为大多数浏览器都实现了ES5的Object.getPrototypeOf()方法
    Object.getPrototypeOf(george) //{ name:'Sam' }

    在IE中不存在__proto__,另外__proto__和prototype并不是等价的
    __proto__实际上是某个实例对象的属性,而prototype则是属于构造器函数的属性

    typeof george.__proto__; //"object"
    
    typeof george.prototype; //"undefined"
    
    typeof george.constructor.prototype; //"object"
    

    所以__proto__只能在学习或调试的环境下使用

  • 相关阅读:
    【转】linux之fsck命令
    【转】linux之mkfs/mke2fs格式化
    【转】linux_fdisk命令详解
    【转】linux之ln命令
    [转]linux的du和df命令
    [转]Linux之type命令
    [转]Linux下which、whereis、locate、find 命令的区别
    [转]Linux的chattr与lsattr命令详解
    get 与post 的接收传值方式
    在asp.net前台页面中引入命名空间 和连接数据库
  • 原文地址:https://www.cnblogs.com/Grani/p/10655005.html
Copyright © 2020-2023  润新知