本文为了解决以下问题:
__proto__(实际原型)和prototype(原型属性)不一样!!!
constructor属性(原型对象中包含这个属性,实例当中也同样会继承这个属性)
prototype属性(constructor.prototype原型对象)
__proto__属性(实例指向原型对象的指针)
首先弄清楚几个概念:
什么是对象?
若干属性的集合
什么是原型?
原型是一个对象,其他对象可以通过它实现继承。
哪些对象有原型?
所有的对象在默认情况下都有一个原型,因为原型本身也是对象,所以每个原型自身又有一个原型(只有一种例外,默认的对象原型在原型链的顶端)
任何一个对象都可以成为原型
接下来就是最核心的内容:
constructor属性始终指向创建当前对象的构造函数。
var arr=[1,2,3];
console.log(arr.constructor); //输出 function Array(){}
var a={};
console.log(arr.constructor);//输出 function Object(){}
var bool=false;
console.log(bool.constructor);//输出 function Boolean(){}
var name="hello";
console.log(name.constructor);//输出 function String(){}
var sayName=function(){}
console.log(sayName.constrctor)// 输出 function Function(){}
//接下来通过构造函数创建instance
function A(){}
var a=new A();
console.log(a.constructor); //输出 function A(){}
以上部分即解释了任何一个对象都有constructor属性,指向创建这个对象的构造函数
//constructor : A
//instance : a
function A(){}
var a=new A();
A.prototype.name="xl";
A.prototype.sayName=function(){
console.log(this.name);
}
console.log(a.name);// "xl"
a.sayName();// "xl"
//那么由constructor创建的instance会继承prototype上的属性和方法
function Person(name){
this.name=name;
}
Person.prototype.sayName=function(){
console.log(this.name);
}
var person=new Person("xl");
console.log(person.constructor); //输出 function Person(){}
console.log(Person.prototype.constructor);//输出 function Person(){}
console.log(Person.constructor); //输出 function Function(){}
如果我们重写(重新定义)这个Person.prototype属性,那么constructor属性的指向就会发生改变了。
Person.prototype={
sayName:function(){
console.log(this.name);
}
}
console.log(person.constructor==Person); //输出 false (这里为什么会输出false后面会讲)
console.log(Person.constructor==Person); //输出 false
console.log(Person.prototype.constructor);// 输出 function Object(){}
//这里为什么会输出function Object(){}
//还记得之前说过constructor属性始终指向创建这个对象的构造函数吗?
Person.prototype={
sayName:function(){
console.log(this.name);
}
}
//这里实际上是对原型对象的重写:
Person.prototype=new Object(){
sayName:function(){
console.log(this.name);
}
}
//看到了吧。现在Person.prototype.constructor属性实际上是指向Object的。
//那么我如何能将constructor属性再次指向Person呢?
Person.prototype.constructor=Person;
接下来解释为什么,看下面的例子
function Person(name){
this.name = name;
}
var personOne=new Person("xl");
Person.prototype = {
sayName: function(){
console.log(this.name);
}
};
var personTwo = new Person('XL');
console.log(personOne.constructor == Person); //输出true
console.log(personTwo.constructor == Person); //输出false
//大家可能会对这个地方产生疑惑?为何会第二个会输出false,personTwo不也是由Person创建的吗?这个地方应该要输出true啊?
//这里就涉及到了JS里面的原型继承
//这个地方是因为person实例继承了Person.prototype原型对象的所有的方法和属性,包括constructor属性。当Person.prototype的constructor发生变化的时候,相应的person实例上的constructor属性也会发生变化。所以第二个会输出false;
//当然第一个是输出true,因为改变构造函数的prototype属性是在personOne被创建出来之后。
function Person(name){
this.name=name;
}
Person.prototype.sayName=function(){
console.log(this.name);
}
var person=new Person("xl");
person.sayName(); //输出 "xl"
//constructor : Person
//instance : person
//prototype : Person.prototype
首先给构造函数的原型对象Person.prototype赋给sayName方法,由构造函数Person创建的实例person会继承原型对象上的sayName方法。
因为ECMAscript的发明者为了简化这门语言,同时又保持继承性,采用了链式继承的方法。
由constructor创建的每个instance都有个__proto__属性,它指向constructor.prototype。那么constrcutor.prototype上定义的属性和方法都会被instance所继承.
function Person(name){
this.name=name;
}
Person.prototype.sayName=function(){
console.log(this.name);
}
var personOne=new Person("a");
var personTwo=new Person("b");
personOne.sayName(); // 输出 "a"
personTwo.sayName(); //输出 "b"
console.log(personOne.__proto__==Person.prototype); // true
console.log(personTwo.__proto__==Person.prototype); // true
console.log(personOne.constructor==Person); //true
console.log(personTwo.constructor==Person); //true
console.log(Person.prototype.constructor==Person); //true
console.log(Person.constructor); //function Function(){}
console.log(Person.__proto__.__proto__); // Object{}
JS是一个非常有魅力的语言也是一个比较烦人的语言,主要就是因为他的特殊性灵活性。JS的原型链,需要深刻的研究才能搞懂。不要纠结细节吧。实在不行就按这个死背住,慢慢就理解了。总之吧就是一句话万物皆对象。
不学会怎么处理对象,你在 JavaScript 道路就就走不了多远。它们几乎是 JavaScript 编程语言每个方面的基础。事实上,学习如何创建对象可能是你刚开始学习的第一件事。
不学会怎么处理对象,你在 JavaScript 道路就就走不了多远。它们几乎是 JavaScript 编程语言每个方面的基础。事实上,学习如何创建对象可能是你刚开始学习的第一件事。
在工作中有时候会看到prototype和__proto__这两个属性,对这两个属性我一直比较蒙圈,但是我通过查阅相关资料,决定做一下总结加深自己的理解
在JS中,函数的本质就是对象,它与其他对象不同的是,创建它的构造函数与创建其他对象的构造函数不一样。那产生函数对象的构造函数是什么呢?是一个叫做Function的特殊函数,通过new Function 产生的对象就是一个函数。
JS中原型是为了实现代码重用的一种仿类机制,不过它跟类又完全不同。它通过给对象添加原型关系(即给某个对象添加__proto__属性)实现一个关联。把共有的方法和属性放到这个关联上即实现了JS的继承。简单来说就是一种委托机制
了解JavaScript中原型以及原型链只需要记住以下2点即可:对象都有__proto__属性,指向构造函数的prototype;构造函数\\函数都有prototype属性,指向构造函数的原型
对象:1,函数对象:有function创造出来的函数2,普通对象:除开函数对象之外的对象,都是普通对象**即普通对象obj是构造函数Object的一个实例,因此:
每个函数都有一个 prototype 属性,函数的 prototype 属性指向了一个对象,这个对象正是调用该构造函数而创建的实例的原型,也就是这个例子中的 cat 和dog 的原型。
这里不介绍原型链。javascript 中有若干长得跟prototype,proto很想的属性/函数,这里简单总结一下他们都是啥,哪个是原型对象,哪个不是。[[Prototype]]这个对象的一个内置槽,对程序员是不可见
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!