JS原型 原型链

跑在最前面的这段话:

1.JS对象分类:程序员

简单记忆:凡是经过new Function()建立的对象都是函数对象,其余均是普通对象。编程

2.只有函数对象才有prototype属性,这个属性是一个指针,指向一个对象(经过该构造函数建立实例对象的原型对象),该属性的指向咱们就能够叫作“原型”或者“原型对象”,即:数组

1 function Person() {};
2 Person.prototype;
3 //constructor:ƒ Person()
4 //__proto__:Object
 var A = Person.prototype;//将A记作原型对象

3.默认状况下,全部的原型或者原型对象都会自动得到一个constructor(构造函数)属性,该属性(是一个指针)指向该函数的构造函数,即:浏览器

1 Person.prototype.constructor == Person

3.js对象均有一个_proto_属性;但_proto_并不是是一个规范属性,只是部分浏览器实现了此属性,对应的标准属性是[[Prototype]];编程语言

  • 每一个对象规定一个私有属性[[prototype]],[[prototype]]所指向的对象也有一个[[prototype]]属性;
  • 可是[[prototype]]语言使用者是没法访问的,不过FirFox的js引擎将其暴露出来,做为公有属性__proto__

4.函数对象和原型对象经过prototype和constructor属性进行相互关联;函数

5.constructor属性this

constructor属性始终指向建立当前对象的构造函数。spa

 1     var arr=[1,2,3];
 2     console.log(arr.constructor); //function Array(){};
 3     var a={};
 4     console.log(arr.constructor);//function Object(){};
 5     var bool=false;
 6     console.log(bool.constructor);//function Boolean(){};
 7     var name="hello";
 8     console.log(name.constructor);//function String(){};
 9     var sayName=function(){}
10     console.log(sayName.constrctor)//function Function(){}
11     
12     //经过构造函数建立instance
13     function A(){}
14     var a=new A();
15     console.log(a.constructor);//function A();
 1    function Person(name){
 2         this.name=name;
 3     }
 4     Person.prototype.sayName=function(){
 5         console.log(this.name);
 6     }
 7     
 8     var person=new Person("lili");
 9     
10     console.log(person.constructor); // function Person(){}
11     console.log(Person.prototype.constructor);// function Person(){}
12     console.log(Person.constructor); // function Function(){}

 1.构造函数:prototype

1 function Foo(name,age){
2   this.name = name;
3   this.age = age;
4   this.class = 'class-1';
5   //return this; //默认有这一行,所以没必要本身写
6 }
7 var f = new Foo('lili',22);

  

2.构造函数的扩展指针

先抛出一个名词:语法糖

在计算机科学中,语法糖(syntactic sugar)是指编程语言中能够更容易的表达一个操做的语法,它可使程序员更加容易去使用这门语言:操做能够变得更加清晰、方便,或者更加符合程序员的编程习惯。

简单理解就是代码的一种简洁写法,好比:

1 var a = {} 是 var a = new Object()的语法糖;
2 var a = [] 是 var a = new Array()的语法糖
3 function Foo(){...}   是var Foo = new Function(){..} 的语法糖

 

3.再抛出五条原型规则:

*全部的引用类型(数组、对象、函数)都具备对象特性,便可自由扩展属性,除了“null”之外;

1 var arr=[];arr.a=100;
2 var obj = {};obj.a=200;
3 function fn(){};fn.a=300;
4 
5 console.log(arr);//[a: 100]
6 console.log(obj);//{a: 200}
7 console.log(fn.a);//200

*全部的引用类型(数组、对象、函数)都有一个__proto__属性(也称隐式原型属性),属性值是一个普通的对象;

1 var arr=[];arr.a=100;
2 var obj = {};obj.a=200;
3 function fn(){};fn.a=300;
4 
5 console.log(arr.__proto__);//[constructor: ƒ, concat: ƒ, pop: ƒ, push: ƒ, shift: ƒ, …]
6 
7 console.log(obj.__proto__);//{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
8 
9 console.log(fn.__proto__);//ƒ () { [native code] }

*全部的函数都有一个prototype属性(也称显式原型属性),属性值也是一个普通的对象;

 1 var arr=[];arr.a=100;
 2 var obj = {};obj.a=200;
 3 function fn(){};fn.a=300;
 4 
 5 console.log(arr.__proto__);//[constructor: ƒ, concat: ƒ, pop: ƒ, push: ƒ, shift: ƒ, …]
 6 
 7 console.log(obj.__proto__);//{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
 8 
 9 console.log(fn.__proto__);//ƒ () { [native code] }
10 
11 console.log(arr.prototype);//undefined 没有prototype属性
12 
13 console.log(fn.prototype);//{constructor: ƒ}

*全部的引用类型(数组、对象、函数)的__proto__属性(即隐式原型属性)指向它的构造函数的" prototype " 属性值(即显显式原型)(===)。

*当试图获得一个对象的某个属性时,若是这个对象自己没有这个属性,那么会在它的隐式原型属性__proto__(即它的构造函数的prototype)中一直往上找寻找该属性,但不会查找自身的prototype,(原型链的造成是真正靠_proto_而非prototype属性);这也就是原型链的造成过程(下图中的红色线条表示的过程)

 1 //构造函数
 2 function Foo(name,age){
 3    this.name=name;
 4 }
 5 Foo.prototype.alertName = function(){
 6   alert(this.name);
 7 }
 8 //建立实例
 9 var f = new Foo('lili');
10 f.printName = function(){
11   console.log(this.name);
12 }
13 //test
14 f.printName();//lili
15 f.alertName();//lili

实例f中自己有个printName属性,打印出来的console.log(this.name)天然就是建立时传进去的"lili";而alertName属性在构造函数Foo中并无,因而顺着实列的隐式原型属性__proto__(即其构造函数的prototype属性)找,便找到了alert(this.name)这句。