zoukankan      html  css  js  c++  java
  • prototype小解

    prototype由来

    在理解prototype前,首先得理解js面向对象编程的私有变量、私有函数,静态变量、静态函数,以及实例变量,实例函数

    私有变量,私有函数

    函数内部通过var定义的变量

    function obj(){
        var a= 1;
        var b= function(){}
    };
    console.log(obj.a); //undefined
    console.log(obj.b); //undefined
    var o= obj();
    console.log(o.a); //undefined
    console.log(o.b); //undefined

    这样a变量,b函数只能在函数体内部获取,外部无法获取,(无论是通过函数本身还是实例获取),所以称为私有变量

    --------------------------------------------------------------------------------------------------------------------

    静态变量,静态函数

    函数外部通过.定义的变量(函数实质上是一种对象)

    function obj(){ 
    };
    obj.a= 1;
    obj.b= function(){};
    console.log(obj.a); //1
    console.log(obj.b); //function(){}
    var o= new obj();
    console.log(o.a); //undefined
    console.log(o.b); //undefined

    通过函数本身依旧能获取,但不能通过实例获取

    -------------------------------------------------------------------------------------------------------------------

    实例变量,实例函数

    通过实例函数定义的变量,函数

    function obj(){
        this.a= 1;
        this.b= function(){};
    };
    console.log(obj.a); //undefined
    console.log(obj.b); //undefined
    var o= new obj();
    console.log(o.a); //1
    console.log(o.b); //function(){}

    不能通过实例函数获取,只能通过实例函数定义的变量获取

    -------------------------------------------------------------------------------------------------------------------

    总所周知,js面向对象最佳方案是通过构造函数实现(虽然通过一般函数也行),

    在创建时私有变量,函数,实例变量,函数使用较多,静态变量,函数很少用,当然这只是本人的经验...

    那么,进入正题,为何需要prototype?,首先请看下面的一个例子~

    function obj(){
        this.a= [];
        this.b= function(){};
    };
    var o1= new obj();
    o1.a.push(1);
    var o2= new obj();
    console.log(o2.a); //[]

    分析:我们通过o1改变了a属性,但通过o2获取仍然不变,为何?

    因为通过构造函数创建的诸个实例,是通过对此函数变量,方法的复制,彼此之间不会共享,不会互相影响

    好比两人通过同一个链接下了同一部电影,其中一个修改了影片资源,那么会对另一个人造成影响么,当然不会!

    那么,问题来了,当实例有几百,上千个,其变量、方法复制几百上千次,这是对资源的极大浪费!

    prototype属性应运而生~请看下面实例

    function obj(){
        this.a= [];
        this.b= function(){};
    };
    obj.prototype.c= [0];
    obj.prototype.d= function(){
        console.log("0");
    }
    var o1= new obj();
    o1.c.push(1);
    o1.d= function(){console.log("1")};
    var o2= new obj();
    console.log(o2.c); //[0,1]
    o2.d(); //0

    c被更改了!证明变量,函数得以共享!(值得一提的是o1.d= function(){console.log("1")};无法改变通过prototype定义的函数,这是本人之前犯过的错)

    这样定义可节约大量空间

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------

    prototype详解:

    prototype与__proto__,继承链:

    依旧从一小段代码开始

    function obj(){
        this.a= [];
        this.b= function(){};
    };
    console.log(obj.prototype);

    输出:

    解析:

    每一个我们定义的函数都有prototype属性,prototype是一个对象,内有constructor属性及__proto__属性(注意下划线长度)

    然后是下面这段:

    function obj(){
        this.a= [];
        this.b= function(){};
    };
    var o= new obj();
    console.log(o.__proto__);

    解析:

    每一个实例皆有__proto__属性,指向其构造函数的prototype属性!

    接着这个:

    function obj(){
        this.a= [];
        this.b= function(){};
    };
    console.log(obj.prototype);
    console.log(Number.prototype);
    console.log(Object.prototype);

    备注:当使用number,object等基本类型时,注意首字母大写,可以把他们也理解为构造函数,函数名是Number,Object等(当然只是这么理解,真实情况当然不是这样~)

    发现除了Object以外,其他类型的prototype都有__proto__属性

    解析:Function,Number,String等本质都是Object的实例!因此都有__proto__属性,Object是源头,自然没有~~,而这恰恰验证了js一切皆为对象的思想!

    Object>基本类型>构造函数>继承构造函数...层层向下,形成继承链!

    -------------------------------------------------------------------------------------------------------------------------------------------------------

    constructor(构建者):

    请看代码:

    function obj(){
        this.a= [];
        this.b= function(){};
    };
    console.log(obj.prototype.constructor);

    console.log(typeof obj.prototype.constructor);

    输出:

    function obj(){
        this.a= [];
        this.b= function(){};
    };

    function

    解析:函数的prototype都有constructor属性,function类型,其值指向函数本身!

    保险起见,为验证是否是函数本身实验以下代码:

    (通过静态属性)

    function obj(){
        this.a= [];
        this.b= function(){};
    };
    obj.c= 1;
    console.log(obj.prototype.constructor.c); //1

    验证成功,真是神奇~

    当然,基本类型,包括Object都有constructor属性

    console.log(Number.prototype.constructor);
    console.log(Object.prototype.constructor);

    输出结果为:

    function Number() { [native code] }
    function Object() { [native code] }

    --------------------------------------------------------------------------------------------------------------------

    prototype相关方法:

    isPrototypeOf 

    判断一个实例是否存在于对象的原型链中

    function obj(){
        this.a= 1;
    };    
    var o= new obj();
    console.log(obj.prototype.isPrototypeOf(o));//true

    注意:值得一提的是此方法只适用于自定义的函数!,不适用于基本类型

    String.prototype.isPrototypeOf("aa");

    Number.prototype.isPrototypeOf(1);

    诸如此类都会返回false!

    hasOwnProperty

    判断实例拥有的属性是本地属性(例如 this.a)还是继承自prototype

    function obj(){
        this.a= 1;
    };    
    obj.b= 1;
    var o= new obj();
    console.log(o.hasOwnProperty("a")); //true
    console.log(o.hasOwnProperty("b")); //false
    console.log("aaa".hasOwnProperty("length")); //true

    本地属性返回true,继承自prototype返回false

    此属性对基本类型有用!

    in

    判断实例是否拥有此属性(对本地属性,prototype属性皆有用

    function obj(){
        this.a= 1;
    };    
    obj.b= 1;
    var o= new obj();
    console.log("a" in o); //true
    console.log("b" in o); //true
    console.log("length" in "aaa"); //报错!

    存在即返回true,

    不可用于基本类型!

  • 相关阅读:
    css:水平居中和垂直居中
    python celery多worker、多队列、定时任务
    python 单例模式
    单例模式
    django 缓存信号等
    redis常用的命令总结
    在python项目中导出项目依赖的模块信息
    面向对象:类中的特殊成员
    python写算法中的栈
    CatLog_小鱼要加油
  • 原文地址:https://www.cnblogs.com/yanze/p/6034445.html
Copyright © 2011-2022 走看看