zoukankan      html  css  js  c++  java
  • prototype 和function关系等总结

    js提供了一些内置类,如Array String Function等,只要有类就有原型。

    1,function ,属性包括 arguments, caller,length,name ,prototype,__proto__,

    2,prototype,属性又分为constructorfunction () {},__proto__Object,

    3,__proto__从别的原型链继承过来可以直接用的,prototype是要加在自己原型链上的,供别人调用,或者直接实例化后,别人可以直接调用转成__proto__的。

    __proto__是永远存在的,都指向下一层,最终是Object。

    4,function 和prototype本身都含__proto__,其实本身也都是对象,自己继承过来的,他们2个也是基本类型的实例。

     js的instanceof是根据prototype来判断两个对象是否存在继承关系,A instanceof B, js会沿着A的原型链查找 直到找到A.__proto__ === B.prototype 返回true。

     一句话__proto__一层层都是指向继承的,最终到基本类型上。

    一,function 

    function定义的是一个Object(对象),而且还是一个很特殊的对象,这个使用function定义的对象与使用new操作符生成的对象之间有一个重要的区别。

    这个区别就是function定义的对象有一个prototype属性,使用new生成的对象就没有这个prototype属性

    prototype是function的一个属性。所有通过function 来定义的对象,都有prototype这个属性。

    通过{}定义的对象字面量是没有prototype的,如

    var a ={1:"a"}
    console.log (a.prototype);
    

     结果是undefined,原因是他已经实例化,

    var a ={1:"a"}
    console.log (a.__proto__);
    

    结果是 Object {} ,相当于new 后的。

    function  的length 参考http://www.cnblogs.com/52cik/p/js-function-length.html

    函数的 length 属性只能得到他的形参个数,而无法得知实参个数。

    function 是Object的实例,他自己的__proto__是Object.prototype

    var A =function (age ){
    	this.age = age;	
    }
    A.prototype.haha = function (){}
    console.log( A instanceof Object)// true 
    console.log( typeof A) // function
    console.log (Object.prototype.toString.call(A)) //[object Function] 
    

      

     数组类型typeof 是object,数组跟object更加接近

    var B =[1,2,3]
    console.log(typeof B)//object
    console.log(typeof A)//function
    

     

    var A =function (age ){
    	this.age = age;	
    }
    A.prototype.haha = function (){}
    var B =[1,2,3]
    console.log(typeof A)//function
    console.log(A instanceof Function)//true
    console.log(A instanceof Object)//true
    console.log(typeof B)//object
    console.log(B instanceof Array)//true
    console.log (Object.prototype.toString.call(A)) //[object Object] 
    

       caller:

       返回一个对函数的引用,该函数调用了当前函数。
       functionName.caller 
       functionName 对象是所执行函数的名称。
      说明
       对于函数来说,caller 属性只有在函数执行时才有定义。如果函数是由顶层调用的,那么 caller 包含的就是 null 。如果在字符串上下文中使用 caller 属性,那么结果和 functionName.toString 一样,也就是说,显示的是函数的反编译文本。

    var A =function (age ){
    	this.age = age;
    	console.log(A.caller)	
    }
    A.prototype.haha = function (){}
    var B = function(type){
       A();	
    }
    B();
    

      返回,最后是B的函数,谁调用我了,返回谁

    function (type){
       A();    
    } 

       

    arguments.callee :返回正被执行的 Function 对象,也就是所指定的 Function 对象的正文。

         [function.]arguments.callee
              可选项 function 参数是当前正在执行的 Function 对象的名称。

         说明 : callee 属性的初始值就是正被执行的 Function 对象。

        callee 属性是 arguments 对象的一个成员,它表示对函数对象本身的引用,这有利于匿名函数的递归或者保证函数的封装性,例如下边示例的递归计算1到n的自然数之和。而该属性仅当相关函数正在执行时才可用。还有需要注意的是callee拥有length属性,这个属性有时候用于验证还是比较好的。arguments.length是实参长度,arguments.callee.length是
        形参长度,由此可以判断调用时形参长度是否和实参长度一致。

    二、prototype

    本身含constructor,__proto__ 
    var A =function (age ){
    	this.age = age;	
    }
    A.prototype.haha = function (){}
    console.log (A.prototype) ;
    

    可以看到的内容

    Object {haha: function}
    constructor: function (age ){
        arguments: null
        caller: null
        length: 1
        name: ""
        prototype: Object
        __proto__: function Empty() {}
        <function scope>
    haha: function (){}
    __proto__: Object
    constructor实际指向的是 函数创建时的那个function。
    function Animal(name) {
       this.name = name;
    }
    Animal.prototype = {
        talk: function() {},
        run: function() {}
    }
    function Dog(age,name) {
       //Animal.call(this,name)  
       this.age=age;
    }
    // 要让 Dog 继承 Animal, 只需:__ 2个_
    Dog.prototype = new  Animal ; // 实例化后
    Dog.prototype.constructor = Dog;//手工的把constructor给暴露出来了。可以通过dog.constructor来调用
    //Dog.prototype = new  Animal ; //Animal的构造函数和自己的prototype也都放到Dog上
    Dog.prototype.haha = function () {};//
    Dog.prototype.haha.tata = 4;
    var dog = new Dog("sdd","bbb"); 
    var animal = new Animal("aaaa");
    console.log(dog);
    console.log(Dog.prototype);

      返回结果如下:

     

     dog.__proto__.__proto__ === Animal.prototype 返回的true。

    原型链作为实现继承的主要方法,其基本思想是:让原型对象等于另一个类型的实例,这样原型对象将包含一个指向另一个原型的指针,相应的,另一个原型中也包含着一个指向另一个构造函数的指针,假如另一个原型又是另一个类型的实例,如此层层递进,就构成了实例与原型的链条,这个链条就称之为原型链.

     另外一个问题,prototype是存储放到共享区域内的,可以共同修改。

    Dog.prototype = Animal.prototype的方法集成,如果子类重写了父类的方法,父类也会受到影响。

       推荐的用法是 

    Dog.prototype.__proto__ = Animal.prototype

    不用写Dog.prototype.constructor = Dog了,constructor 没有被覆盖,Dog本身就有了。

    参考可以看下下面的例子,   http://www.cnblogs.com/qiantuwuliang/archive/2011/01/08/1930548.html

    代码 
    
    function Person(name)   
    {   
       this.name=name;   
       this.showMe=function()   
            {   
               alert(this.name);   
            }   
    };   
      
    Person.prototype.from=function()   
    {   
      alert('I come from prototype.');   
    }   
    var father=new Person('js');//为了下面演示使用showMe方法,采用了js参数,实际多采用无参数   
    alert(father.constructor);//查看构造函数,结果是:function Person(name) {...};   
    function SubPer()   
    {   
    }   
    SubPer.prototype=father;//注意这里   
    SubPer.prototype.constructor=SubPer;   
      
    var son=new SubPer();   
    son.showMe();//js   
    son.from();//I come from prototype.   
    alert(father.constructor);//function SubPer(){...}   
    alert(son.constructor);//function SubPer(){...}   
    alert(SubPer.prototype.constructor);//function SubPer(){...}
    

      

     关于prototype是共享和prototype的作用域问题

    function Tree(x){
    	this.value = x;	
    }
    Tree.prototype.children = [1,2];
    
    var a =new Tree(2);
    a.children=3;
    var b = new Tree(4);
    b.children=5;
    var c = new Tree(6); 
    console.log (c.children)//[1,2]
    

     这个对 a.__proto_ 没有做修改,最后依然是 a.__proto_ === Tree.prototype

       a.children=3,相当于在a这个对象下面直接加了个children的属性。

    function Tree(x){
    	this.value = x;	
    }
    Tree.prototype.children = [1,2];
    
    var a =new Tree(2);
    a.children.push("3");
    var b = new Tree(4);
    b.children.push("5");
    var c = new Tree(6); 
    console.log (c.children);//[1,2,"3","5"]
    

      a.children相当于开始是undefined,如果直接复制的话,就是在a对象下加属性了,然后在.操作,相当于从原型链上去取了。

    var A = function(b){
         this.b =b;	
    }
    A.prototype.hh="222";
    
    $.extend(A.prototype,{
    	b:"333",
    	hh:"444"	
    });
    var a = new A();
    console.log(a);
    

      

    A
    1. bundefined
    2. __proto__Object
      1. b"333"
      2. constructorfunction (b){
        1. argumentsnull
        2. callernull
        3. length1
        4. name""
        5. prototypeObject
        6. __proto__function Empty() {}
        7. <function scope>
      3. hh"444"
      4. __proto__Object
  • 相关阅读:
    CentOS安装Nginx Pre-Built
    CMake设置编译参数
    SQLServer脚本编写
    使用QNetworkAccessManager实现Qt的FTP下载服务
    使用CMD命令设置IP
    IIS6(Win2003) 使用.net 4.0 后,默认文档失效解决方案。
    windows7打印时,显示脱机,提示“服务器打印后台处理程序服务没有运行”。
    阻止浏览器自动填表
    Java经典编程题50道之四
    Java经典编程题50道之三
  • 原文地址:https://www.cnblogs.com/danghuijian/p/3755755.html
Copyright © 2011-2022 走看看