二 、函数高级 (一)-- 原型与原型链

一、原型与原型链

1.1 显示原型与隐式原型

	
	1、显示原型			
			1) 每个函数都有一个prototype属性,即显示原型。它默认指向一个Object空实例对象,即原型对象。
			   但是Objct函数除外。
							
			2) 函数的prototype属性:在定义函数时自动添加的,默认指向一个Object空实例对象。
										
										function Fn(){
											//内部代码:this.prototype={}
										}

	2、隐式原型
			1) 每个对象都有一个"__proto__"属性,即隐式原型,它默认指向构造函数"prototype"属性指向的原型对象。
			
			2) 对象的__proto__属性:在创建对象时自动添加。默认指向构造函数的prototype属性指向的值。
										var s=new Fn();
										//内部代码 : s.__proto__=Fn.prototype;
	
	3、实例对象隐式原型的值等于构造函数显示原型的值。他们都指向原型对象。

>>>>>> 每个函数都有一个prototype属性,即原型属性。它默认指向一个Object空实例对象,即原型对象。

    function Person(){
      
    }

    Person.prototype.a="abc"

    //每个函数都有一个prototype属性,它默认指向一个Objct空对象
    console.log(Person.prototype)
    

二 、函数高级 (一)-- 原型与原型链

>>>>>> 每个对象都有一个__proto__属性,即隐式原型。它默认指向构造函数显示原型指向的原型对象。
    function Person(){
        this.age=12
    }

    var ss=new Person();

    console.log(ss.__proto__);
    console.log(ss.__proto__==Person.prototype);//true
    

二 、函数高级 (一)-- 原型与原型链

>>>>>> 实例对象隐式原型属性的值等于构造函数显示原型的值,它们都指向原型对象

    function Person(){
      
    }
    
    //1.每个函数都有prototype属性,即显示原型属性
    console.log(Person.prototype)

    //2.每个实例对象都有一个—__proto__属性,即隐式原型属性
    var o1=new Person();
    console.log(o1.__proto__)

    //3.实例对象的隐式原型的值等于构造函数的显示原型的值。他们都指向原型对象
    console.log(Person.prototype===o1.__proto__)

    

二 、函数高级 (一)-- 原型与原型链

>>>>>> 函数的显示原型与对象的隐式原型创建原理
	
	//函数的prototype属性:在函数加载时自动添加
    function Person(){
        //内部代码:  this.prototype={};
    }
	
	//对象的__proto__属性:在创建对象时自动添加
    var p=new Person();  // 内部代码: p.__proto__=Person.prototype

二 、函数高级 (一)-- 原型与原型链

1.2 原型对象


	  1、函数与原型对象内部互相引用。
		    	每个函数都自带一个prototype属性,即显示原型。它默认指向一个Object空对象,即原型对象。			  
		     	原型对象中也默认有一个constructor属性,它默认指向该函数。				
	  
	  2、所有函数的原型对象默认都是Object实例。
	     但是Object函数的原型对象不是Object实例。

   ,
>>>>>> 原型对象中默认有一个constructor属性,它默认指向该函数。

    function Person(){

    }

    //原型对象
    console.log(Person.prototype)
    console.log(Person.prototype.constructor === Person)

二 、函数高级 (一)-- 原型与原型链

>>>>>> 函数与原型对象相互引用

二 、函数高级 (一)-- 原型与原型链

案例


    function Person(){
        this.sayName=function(){
            console.log("123")
        }
    }

    //每个函数都有一个prototype属性,它默认指向一个Objct空对象
    console.log(Person.prototype)

    //原型对象中有一个constructor属性指向该函数
    console.log(Person.prototype.constructor)
    console.log(Person.prototype.constructor===Person) //true

二 、函数高级 (一)-- 原型与原型链

>>>>>> 所有函数的原型对象默认都是Object实例,但是Object函数的原型对象不是Object实例

    function Person(){
        this.age=12
    }

    console.log(Person.prototype instanceof Object);  //true
    console.log(Function.prototype instanceof Object) //true

    console.log(Object.prototype instanceof Object)   //false


二 、函数高级 (一)-- 原型与原型链

二、原型链

2.1 原型链

	
	1、原型链实质上就是隐式原型链。它的作用就是查找对象的属性。
			
																																																																																												访问一个对象的属性时,首先在自身作用域中查找。
	   		如果没有,就会沿着隐式原型这条链("__proto__")向上查找,找到就返回。
	   		如果没找到就返回undefined。
	   	
	2、原型链只能用于查找对象的属性。当设置对象的属性时,不会查找原型链。
	
	3、JS通过原型链实现继承。所有实例都可以访问原型对象的属性和方法。
	  
	4、Object函数的原型对象(Object.prototype)
		  		1) 它位于原型链的最顶端。
		  					原因: Object.prototype.__proto__ =null.
		  		
		  		2) Object函数的原型对象有许多内置方法,比如 toString()、hasOwnProperty()。
		  		3) 所有函数或实例都直接或间接继承该对象的属性。

1)JS通过原型链实现继承。所有实例对象都自动拥有原型对象中的属性或方法。
  
   function Person(){        
            this.test1=function(){            			
                        console.log("test1")       
            }    
    }    
    Person.prototype.test2=function(){         
           console.log("test2")    
    }    

	var p=new Person();    
	p.test1();   
	p.test2();    
	console.log(p.toString()) 
	
	

二 、函数高级 (一)-- 原型与原型链

2)原型链就是查找对象对象的属性,设置对象属性时,不会到原型链中查找。
>>>>>> 案例1:原型链只能用于查找对象的属性。设置对象的属性时,不会查找原型链。

    function Person(){

    }

    Person.prototype.a=12;

    var s=new Person();
    console.log(s.a); //12 

    var s2=new Person();
    s2.a=1222;

    console.log(s.a); //12
    console.log(s2.a); //1222
    

二 、函数高级 (一)-- 原型与原型链

>>>>>> 案例2:调用原型对象的方法,原型对象的方法中的this指的也是传入的对象

    function Person(){

    }

    Person.prototype.setName=function(name){
        this.name=name;
    };

    var s=new Person();
    s.setName("123")

    var s2=new Person();
    console.log(s)
    console.log(s2)
    

二 、函数高级 (一)-- 原型与原型链

2.2 原型链内部原理图

1)原型链的原理图

    function Person() {

        this.test1 = function () { 
            console.log("test1") 
        }
        
    } 
    Person.prototype.test2 = function () {
             console.log("test2") 
    }    
    
    var p = new Person(); 
    p.test1(); 
    p.test2(); 
    
    console.log(p.toString())
    

二 、函数高级 (一)-- 原型与原型链

	
	解析:
		p.test1()    首先查找到p对应的内存,查找test1属性,找到后调用即可。
		
		p.test2()    首先查找到p对应的内存,查找test2属性,找不到,
		             就会沿着__proto__属性指向的原型对象中查找。
		
		p.toString() 首先查找到p对应的内存,查找toString属性,找不到,
		             就会到p对应的原型对象中查找,找不到。
		             再次到原型对象的原型对象中查找。
		
		
2)Object、Function内部原理图
	
	1、所有函数都有一个显示原型属性,它默认指向一个Object空实例对象,即原型对象。
	   但是Object除外。
	
	2、所有对象都有一个隐式原型属性,它默认指向构造函数显示原型属性指向的原型对象。
	
	3、所有函数都是Function的实例。(包含Function也是Function的实例)
			
			1) 所有函数都有显示原型属性和隐式原型属性。
			   所有函数的隐式原型属性都指向构造函数Function显示原型属性指向的原型对象。
			
			2) Function的隐式原型等于Function的显示原型。他们都指向同一个原型对象。		   
			
	   

二 、函数高级 (一)-- 原型与原型链

3)原型链原理测试案例
>>>>>> 解析案例1

	function Person(){}

    Object.prototype.a=function(){console.log("a")}

    Function.prototype.b=function(){console.log("b")}



    var s=new Person();
    s.a();  //可以输出
    s.b; 	//报错

    Person.a(); //可以输出
    Person.b(); //可以输出

二 、函数高级 (一)-- 原型与原型链

>>>>>> 解析案例2
    function A(){}

    A.prototype.n=1;


    var b=new A();

    A.prototype={
        n:2,
        m:3
    };

    var c= new A();
    console.log(b.n, b.m , c.n , c.m)  //1 undefined 2 3

二 、函数高级 (一)-- 原型与原型链

2.3 总结


	1、每个函数都有一个prototype属性,即显示原型。它默认指向一个Object空实例对象,即原型对象。
	   但是Object函数除外。Object函数指向的原型对象不是Object类型。
		

	2、每个对象都有一个__proto__属性,即隐式原型。它默认指向构造函数显示原型指向的原型对象。
	
	3、实例对象隐式原型属性的值等于构造函数显示原型的值,它们都指向原型对象。
	
	4、构造函数与原型对象互相引用。
	
	5、所有函数都是Function的实例,包括Function本身。
			
			1) 每个函数都有显示原型与隐式原型。
			   并且每个函数的隐式原型都同时指向Function显示原型指向的原型对象。
			   
			2) Function函数是它自身的实例。所以Function函数的隐式原型和显示原型都指向同一个原型对象。
   					Function.__proto__=Function.prototype
	
			
	
	6、Object.prototype是原型链的尽头。
					由于Object.prototype.__proto__为null。所以Object的原型对象是原型链的尽头。
	
	7、所有函数的原型对象默认都是Object实例,但是Object函数的原型对象不是Object实例。
	
1)所有函数都是Function的实例,包括Function本身
	
	声明一个函数或创建函数对象两者等价:
		
			    function  Person(){  }
			
			    var Person=new Function();
	    
>>>>>> 每个函数都有隐式原型和显示原型。并且每个函数的隐式原型都同时指向Function显示原型指向的原型对象。
    function  Person(){
        
    }

    function  Person2(){
        
    }

    //每个函数都有一个隐式原型,它默认指向一个空实例对象
    console.log(Person.prototype); 


     //所有函数都是Function的实例。所以每个函数都拥有隐式原型和显示原型
    console.log(Person.__proto__);


    //由于所有函数都是Function的实例。所以函数隐式原型都同时指向Function函数的显示原型指向的原型对象。
    console.log(Person.__proto__===Function.prototype); 
    console.log(Person2.__proto__===Function.prototype); 

二 、函数高级 (一)-- 原型与原型链

>>>>>> Function函数对象是它自身的实例,所以Function的隐式原型和显示原型相等。
	
	//var Function = new Function()
    console.log(Function.prototype===Function.__proto__)

2)每个函数的显示原型都默认指向一个Object空实例对象。但是Object函数的显示原型对象除外。

    function Person(){}

    console.log(Person.prototype  instanceof Object)  //true
    console.log(Function.prototype instanceof Object) //true

    console.log(Object.prototype instanceof Object)  //false

3)Object函数的原型对象是原型链的尽头。主要是由于它的原型对象的隐式原型为null。
  
    console.log(Object.prototype.__proto__) //null

三、instanceOf 判断(实质上就是原型链的应用)

	
	1、instanceOf 判断。实质上就是依赖于原型链。		
	
	2、表达式: A instanceOf B
			判断B的显示原型指向的原型对象是否在A的原型链中。如果是,返回true。、
			

    console.log(Object instanceof Function);  //true
    console.log(Object instanceof  Object);   //true
 
    console.log(Function instanceof Function);  //true
    console.log(Function instanceof Object);    //true

    function Person(){}
    console.log(Object instanceof Person);  //false
    

二 、函数高级 (一)-- 原型与原型链

上一篇:# js判断数据类型的四种方法


下一篇:spring prototype bean 获取处理