函数对象
对于函数对象来说,它的proto都是指向Function.prototype。函数对象可以是如下几种构造器:Number,Boolean,String,Object,Function,Array,RegExp,Error,Date
//举个栗子
Number.__proto__ === Function.prototype;
Number.constructor === Function
要记住:所有的构造器都来自于Function.prototype,甚至包括根构造器 Object
及Function
自身。
但是Math、JSON一直都是以对象的形式存在的,不需要使用New,所以他们的__proto__
指向的是Object.prototype.
//再举个栗子
Math.__proto__ === Object.prototype;
Math.constructor === Object
我们在之前已经提过,除了Function.prototype的类型是function,其他的构造器的prototype都是一个对象。
typeof Function.prototype //function
typeof Object.prototype //Object
typeof Error.prototype //Object
typeof Date.prototype //Object
综上所述:所有的构造器的__proto__
都是Function.prototype
,那么我们think一下Function.prototype的__proto__
是什么呢?经过验证得出:
Function.prototype.__proto__ === Object.prototype
从侧面验证了所有的构造器都是一个普通的js对象,与此同时构造器也继承了Object.prototype上面的所有的方法:toString,valueOf等,而之所以Object.prototype.__proto__ === null
是因为原型链已经到顶了~~~
Prototype
我们研究了这么多的原型和原型链的知识,但是为什么我们一定要定义prototype
属性呢,对于ECMAScript中的引用类型来说,prototype是保存着他们所有实例方法的真正的地方,也就是说我们在使用一些很平常的方法,例如:toString()和valueOf() ,这些方法都是保存在prototype上面的,只不过是在使用的时候通过各自的对象进行实例的访问罢了。

当我们声明一个实例的时候:
var Student = new Object()
,这个时候我们发现Student
继承了Object的原型对象Object.prototype
的所有的方法。这就是我们定义且使用prototype的初衷。、对于Js内置的构造器我们已经有了一定的认识,我们看一下我们自己定义的构造器,我们先定义一个
Student
的构造器:
function Student(name){
this.name = name;
}
var p = new Student ('kim')
//p.__proto__=== Student.prototype
粗浅的解释一下:p
是Student
的实例对象,p的内部原型总是指向Student
的原型对象prototype
。
function Student(name){
this.name = name;
}
var p = new Student ('kim');
///p.__proto__=== p.constructor.prototype;
因为每一个对象都有一个constructor的属性,可以用来获取它的构造器,所以注释里面的结果也是恒等于的。
现在我们已经弄明白了上面是原型属性,以及构造函数、原型、__proto__
之间的关系,我们考虑如果我们修改来原型,会有什么影响:
function Student(name) {
this.name = name
}
// 修改原型
Student.prototype.getName = function() {}
var p = new Student('kim')
//p.__proto__ === Student.prototype
//p.__proto__ === p.constructor.prototype
上面的情况很好被理解,但是如果现在的情况是我们重写了原型,那现在的情况还会是这样吗?我们看一下下面的例子:
function Student(name) {
this.name = name
}
// 修改原型
Student.prototype ={getName: function() {}}
var p = new Student('kim')
//p.__proto__ === Student.prototype
//p.__proto__!== p.constructor.prototype
这个时候,我们看到了p.__proto__!== p.constructor.prototype
和上面比较发生了变化,这是为什么呢?因为Student.prototype
赋值的是一个直接的对象直接量,使用对象直接量方式定义的对象,他的构造器(constructor
)指向的是根构造器Object
,也就是说Object.prototype
是一个对象,这个对象就是上面最开始打出的值,这个值和{getName: function() {}}
一定是不相等的。
总结
- 原型和原型链是JS实现继承的一种模型。
- 原型链的形成是是通过
__proto__
实现的,而不是prototype,prototype主要是进行属性共享的。
网友评论