Javascript规定,每个函数都有一个prototype对象属性,指向另外一个对象(原型链上面的)。
prototype(对象属性)的全部属性和方法,都会被构造函数的实例继承。这意味着,咱们能够把那些不变(公用)的属性和方法,直接定义在prototype对象属性上。闭包
prototype就是调用构造函数所建立的那个实例对象的原型(proto)。框架
prototype可让全部对象实例共享它所包含的属性和方法。也就是说,没必要在构造函数中定义对象信息,而是能够直接将这些信息添加到原型中。函数
实例对象与原型之间的链接,叫作原型链。proto( 隐式链接 )
JS在建立对象的时候,都有一个叫作proto的内置属性,用于指向建立它的函数对象的原型对象prototype。
内部原型(proto)和构造器的原型(prototype)
一、每一个对象都有一个proto属性,原型链上的对象正是依靠这个属性连结在一块儿
二、做为一个对象,当你访问其中的一个属性或方法的时候,若是这个对象中没有这个 方法或属性,那么Javascript引擎将会访问这个对象的proto属性所指向上一个对 象,并在那个对象中查找指定的方法或属性,若是不能找到,那就会继续经过那个对象 的proto属性指向的对象进行向上查找,直到这个链表结束。学习
每个函数都有一个原型属性prototype(对象属性),里面放置的是共有、公有的属性或者方法。(通常状况属性是私有的)。注意,只有函数才有prototyoe属性,this
function Person() { } var p = new Person() console.log(Person.prototype); // Object{} console.log(p.prototype); //undefined
这个例子能够发现,函数是存在prototype属性的prototype
在 Javascript 语言中,constructor 属性是专门为 function 而设计的,它存在于每个 function 的prototype 属性中。这个 constructor 保存了指向 function 的一个引用。设计
function Person() { } var p = new Person() console.log(Person.prototype); // Object{} console.log(p.prototype); // undifined console.log(p.constructor); //function Person(){} 此处的p是经过 Person函数构造出来的,因此p的constructor属性指向Person console.log(Person.constructor); //function Function(){} 以前提过,每一个函数实际上是经过new Function()构造的 console.log({}.constructor); // function Object(){} 每一个对象都是经过new Object()构造的 console.log(Object.constructor); // function Function() {} Object也是一个函数,它是Function()构造的 console.log([].constructor); //function Array(){}
console.log(Object.constructor); // function Function() {}
可能你们对于这个有些不理解,毕竟咱们实际开发中哪见过这玩意code
console.log(Function instanceof Object); // true console.log(Object instanceof Function); // true
这样你们是否是就明白了呢 函数是对象构造的 对象也是函数构造的,俩者便是函数也是对象,因此为何构造函数它是一个函数却返回一个对象,俩者是互相继承的关系对象
var o1 = new f1(); typeof o1 //"object"
function Person(name,age){ this.name = name; this.age = age; this.sayHello = function(){ console.log(this.name + "say hello"); } } var girl = new Person("bella",23); var boy = new Person("alex",23); console.log(girl.name); //bella console.log(boy.name); //alex console.log(girl.sayHello === boy.sayHello); //false
再看下面的代码blog
function Person(name,age){ this.name = name; this.age = age; } Person.prototype.sayHello=function(){ console.log(this.name + "say hello"); } var girl = new Person("bella",23); var boy = new Person("alex",23); console.log(girl.name); //bella console.log(boy.name); //alex console.log(girl.sayHello === boy.sayHello); //true
var obj = {} 此处等价于 var obj = new Object() console.log(obj.__proto__ === Object.prototype)//true
__proto__
的内置属性,用于指向建立它的构造函数的原型对象。根据前面的例子咱们很清楚,obj是经过new Object 构造出来的一个对象,那咱们Object的原型对象就是Object.prototype,在Object下面构造出来的全部对象,都有一个__proto__
指向它的原型,咱们称这个为原型链
var obj = [] console.log(obj.__proto__ === Array.prototype)//true
这个也是同样的道理
console.log(Array.prototype.constructor)//Array{}
function Person(name,age){ this.name = name; this.age = age; } Person.prototype.sayHello=function(){ console.log(this.name + "say hello"); } var girl = new Person("bella",23); var boy = new Person("alex",23); console.log(Person.prototype.constructor); //Person console.log(girl.__proto__==Person.prototype); //true console.log(girl.constructor==Person); //true
如今看是否是特别简单 注意这里是两个下划线__proto__
叫 杠杠proto杠杠
接下来给一串代码
function Person(){ } var person1=new Person()
快速回答
1.person1.__proto__
==
2.person1.constructor
==
3.Person.__proto__
==
4.Person.prototype.constructor
==
5.person1.prototype.constructor
==
6.Person.prototype
==
你们能够测测输入的答案打印是否是为true 若是你很快打出,说明你理解的已经很透彻了
function A(){ } function B(a){ this.a = a; } function C(a){ if(a){ this.a = a; } } A.prototype.a = 1; B.prototype.a = 1; C.prototype.a = 1; console.log(new A().a); //1 console.log(new B().a);//undefined console.log(new C(2).a);//2
咱们先观察第一个
new A() 很明显它是A()构造的实例对象,在下面A函数prototype共享了一个属性a=1,那么实例对象也能够经过这个属性访问到他的值==1
第一个比较简单,咱们看第二个
第二个实际上是个坑,首先B()函数它声明的时候设置了一个参数,注意里面的方法this,此时this指向的是window,咱们都知道,然而在构造函数以后this指向了new B(),然而此时B 没有传入参数,也就是说此时的参数a==undefined,
所以new B()下的属性a==this.a==undefined (不知道这么说能不能理解 ̄□ ̄||)
若是咱们给B 传入一个数(能够是a,但a必定要先声明)
console.log(new B(3).a); //3 console.log(new B(5).a); //5
这样应该就好理解了,总不能咱们本身设置的属性还覆盖不来爸爸给你的属性吧
第三个很好理解,从第二个的角度分析,若是传入参数,输出参数,若是没有 输出1
function Fun(){ var getName = function(){ console.log(1); } return this; } Fun.getName = function(){ console.log(2); } Fun.prototype.getName = function(){ console.log(3); } var getName = function(){ console.log(4); } function getName(){ console.log(5); } Fun().getName(); //4 getName(); //4 new Fun().getName();//3 new new Fun().getName();//3
作题必定要一步步来,先看第一个 Fun().getName();
很明显此时是Fun()调用getName(),咱们看看Fun(),注意,函数的返回值永远是return,此处return返回了this,在函数中这里的this指向window,也就是说第一步Fun( )返回的是window,转换一下就是window.getName(),
咱们在什么找一下全局的getName,最终输出4
第二个其实很简单,我感受就是来迷惑咱们的,前面省略了window,很明显仍是4
第三个也太简单了,只要你理解了我上面写的内容,一看就知道输出3
第四个,两个new? 不要慌 咱们来分析一下
new后面跟的确定是函数,用来构造实例对象,因此new Fun()这是不能拆的,
很明显此时new Fun()是一个构造函数,虽然称之为函数,但其实它是一个对象,由于函数是方法,而方法是不能调用属性的,可是对象能够,既然是对象,何来new 构造呢,因此此处分析能够获得new Fun ().getName才是一体连着的,
那很明显就是原型下的方法咯,因此输出3
转载于:https://www.jianshu.com/p/72156bc03ac1