最近在看到了JavaScript的原型链这里,一直认为是比较复杂的就去多了解了下,本来是准备写点什么的,发现脑子里乱乱的无从下手,然后又去翻查了各种资料才有点眉目,就此算是做个总结一下吧。
原型
JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象。对象以原型为模板继承原型的方法和属性,以此类推就成了“原型链”。具体的说:"它将通过new关键字创建的<对象实例>链接会创建它们的<构造函数>" 。就这样,我们可以共享或继承通用的方法和属性。为什么有原型和原型链,这就和js的继承机制设计思想有关了,如果有兴趣可以去看阮一峰的这篇博客了解下。
首先我把需要注意的几点放上面,思维图放文章后面。
1 .每个对象都具有一个__ proto __ 属性,并且指向自身的构造函数的prototype。
2 .创建一个函数 数组,都会有一个prototype(原型对象,不管是否当做构造函数)
3 .每个构造函数都具有名为prototype的方法(构造函数标准为首字母大写,例如Function()Object()等以及自己创建的)
4 .调用构造函数的模式:
var 对象实例 = new 构造函数()
原型链概要
JavaScript中创建的每个对象设置一个原型指向它的原型对象,例如当我们访问obj.xxx时,JavaScript引擎就会在当前对象上寻找,如果没有就回去他的原型对象上寻找,如果还没有就会去下一个原型对象,直到Object.prototype还没有就会指向null,并且返回一个undefined。所以js为了给你个undefined可谓经历了一波三折啊
var obj = [1, 2, 3]; console.log(obj.xxx) //undefined
1.在obj对象中查找该属性; 如果没有找到就去下一家 2.则在Array.prototype中查找该属性; 但它在那里也没有定义 3.最后查找的地方就是Object.prototype还没有? 继续向下走只有最终指向的null了 没办法,只能返回给你undefined~~~
其原型链是:
obj ----> Array.prototype ----> Object.prototype ----> null
当我们创建函数是也同样如此(函数也是对象)
function fun(){
console.log(function)
}
fun.__proto__ === Function.prototype
Function.prototype.__proto__ === Object.prototype
Object.prototype.__proto__ ===null
其原型链是:
fun----> function .prototype ----> Object.prototype ----> null
构造函数
除了使用数组和函数,以及全局对象(临时转换),我们还可以通过构造函数的方式先创建对象,来定义一个构造函数。
调用构造函数的模式:var 对象实例 = new 构造函数()
(调用构造函数千万不能忘记写new。为了区分普通函数和构造函数,按照约定,构造函数首字母应当大写,而普通函数首字母应当小写)
function Student(){
this.name=Leonardo
}
//我们构造一个函数Student,这个数有Function生成
var stu = new Student()
//我们创建一个函数stu,设个函数有Student生成(构造函数)
stu.__proto__ === Student.prototype
//stu的__proto__ 指向它的构造函数
Student.prototype.__proto__ === Object.prototype
//Student.prototype的__proto__ 指向它的构造函数
Object.prototype.__proto__ ===null
//Object.prototype.的__proto__ 指向null
constructor(构造函数属性)
我们除了使用. __ proto __ 链接,还可以使用构造函数属性:
事实上,.__ proto __ === constructor.prototype
function fun(){
console.log(function)
}
fun.constructor.prototype=== Function.prototype
Function.prototype.constructor.prototype=== Object.prototype
Object.prototype.constructor.prototype===null
prototype属性
prototype 属性是继承成员被定义的地方,继承的属性和方法是定义在 prototype 属性之上的。
对象的__ proto __ 属性通常与其构造函数的prototype属性相互对应;
所有构造函数的的prototype方法的__ proto __ 都指向Object.prototype(除了....Object.prototype自身)
替换prototype属性的默认值
我们可以用一个新值来替换prototype属性的默认值,但是需要特别注意的是:这么做会删除在"预制"原型对象中找到的默认的constructor属性。继承原型属性的实例总是能够获得最新值
用新对象替换prototype属性不会更新以前的实例
创建一个实例时,该实例将在实例化时绑定至"刚完成"的原型,提供一个新对象作为prototype属性不会更新已创建的实例和原型之间的连接,所以一旦开始创建实例,就不应用一个新对象那个来替换对象的原型,这样将会导致实例有一个指向不同原型的链接
自定义构造函数实现原型继承
当我们在自定义构造函数时,同样可以实现原型继承。
原型链概念图,可以结合理解: