原型[prototype]:函数
为其余对象提供共享属性的对象。this
每一个函数都有一个原型(prototype)属性,这个属性是一个指针,指向一个对象,这个对象包含特定实例共享的一些属性和方法。spa
以例服人:prototype
这个例子说明了原型对象是共享的,而且是一个指针,而且对象的实例中也有指向prototype指向对象的指针。指针
function Animal(name) { this.name = name || "动物"; } Animal.prototype.runs = function() { console.log(this.name + ',跑起来了\n') } var dog = new Animal('小狗') dog.runs() //输出"小狗跑起来了"
// 下面增长的方法,dog对象可使用吗?
Animal.prototype.hi = function() {console.log('hi')} dog.hi() //输出"hi",说明原型属性是一个指针,指向一个共享对象,无论先添加的仍是后添加的方法都能调用
//dog做为一个Animal实例,他的__proto__属性和Animal.prototype指向同一个对象,因此才可使用原型的方法。
console.dir(dog) // 查看 dog.__proto__
// dog.__proto__ & Animal.prototype
console.log(dog.__proto__ === Animal.prototype) //true,有相同的指针地址
原生构造函数的原型对象[不单函数有原型对象]code
console.dir(Object.prototype)对象
console.dir(Array.prototype)blog
console.dir(String.prototype)继承
console.dir(Date.prototype)原型链
再看一个__proto__ & prototype的例子
var obj = { } obj.toString() // "[object Object]"
//obj 对象为何有 toString 方法? //由于 obj 对象是 Object 构造函数的实例,obj 对象的原型指针指向 Object.prototype 对象。console.log(obj.__proto__ === Object.prototype )
经过原型关系图理解:
再看一个函数的原型的例子
var obj = {name: 'jack'} function getName() { console.log(this.name) } // 问题:Animal.call 方法来自哪?
getName.call(obj) //来自Function对象
console.dir(getName) console.log(getName.__proto__ === Function.prototype) //true
console.log(Function.prototype.__proto__ === Object.prototype) //true
经过原型关系图理解
原型继承:
function Animal() { this.name = '动物' } Animal.prototype.runs = function() { console.log(this.name + ',跑起来了\n') return this } function Bird() { this.name = '鸟' } Bird.prototype = new Animal() //让Bird的原型等于Animal的实例,由于new Animal中有__proto__指向Animal.prototype的指向(沿着原型链寻找),此处也能够写为Bird.prototype = Animal.prototype Bird.prototype.fly = function() { console.log(this.name + ',飞走了\n') return this } function Crow(name) { this.name = name || '乌鸦' } Crow.prototype = new Bird() Crow.prototype.drink = function() { console.log(this.name + ',喝饱了水\n') return this } var crow = new Crow('一只可爱的小乌鸦') crow.drink().runs().fly() console.dir(crow)
输出结果:
原型总结:
每个构造函数都有一个和其对应的原型对象。
构造函数的 prototype 属性和其实例对象的 “__proto__” 属性指向同一个对象。
某构造函数的全部实例对象,共享一份原型对象。
全部的对象均可以经过 “__proto__” 属性,最终链接到 Object.prototype 对象。
构造函数用 prototype 来定义原型的属性和方法,实例对象用 “__proto__” 来查找原型的属性和方法。
当查找一个对象的属性或方法时,JS引擎会向上遍历其原型链,直到找到给定名称的属性为止。若是最终在 Object.prototype 对象仍然没有找到此属性或方法,则返回 undefined 值。