如果还不是很清楚JS原型链的小伙伴,可以把下面的代码运行一下,细细品味~
1 // 1.构造函数 2 function Dog(name){ 3 this.name = name 4 this.action = function(msg){ 5 console.info(msg) 6 } 7 } 8 9 // 2.使用构造函数Dog创建的实例对象 10 var xiaohua = new Dog('小花') 11 // 实例对象xiaohua可以使用构造函数中的属性、方法 12 console.info(xiaohua.name) // 小花 13 var xiaohei = new Dog('小黑') 14 xiaohei.action('摇尾巴') // 摇尾巴 15 16 // 3.直接使用构造函数中的方法,每个实例对象中方法都会复制一份,造成内存浪费 17 // 如下两个实例对象相同的方法不相等 18 console.info(xiaohua.action === xiaohei.action) // false 19 20 // 4.使用原型 21 // 每一个构造函数均有一个prototype属性,该属性是一个对象,其所有方法和属性都被构造函数所拥有, 22 // 因此,可以把不变的属性和方法定义在prototype对象上,所有的实例都可以共享这些属性和方法 23 24 // 给构造函数Dog的原型添加属性和方法 25 Dog.prototype.favourite = '骨头' 26 Dog.prototype.barking = function (){ 27 console.info('汪汪汪...') 28 } 29 // 实例中可以直接使用 30 console.info(xiaohua.favourite) // 骨头 31 // 而且原型中的方法是共享的 32 console.info(xiaohua.barking === xiaohei.barking) // true 33 34 // 5.构造函数的原型对象和实例的关系 35 // 每个实例对象都有一个__proto__属性(原型),指向构造函数的原型对象prototype,所以实例对象可以使用构造函数原型中的方法 36 console.info(xiaohua.__proto__ === Dog.prototype) // true 37 38 // 实例对象可以使用方法:1.自身拥有的方法,2.顺着__proto__找到的构造函数prototype的方法 39 40 41 // 6.原型对象prototype和构造函数的关系 42 // 原型对象prototype有constructor属性,该属性为构造函数本身 43 console.info(Dog.prototype.constructor === Dog) // true 44 // 有因为实例对象的__proto__等于构造函数的prototype,所以每个实例的__proto__.constructor即是构造函数 45 console.info(xiaohua.__proto__.constructor === Dog) // true 46 console.info(xiaohei.__proto__.constructor === Dog) // true 47 48 // 通过实例的__proto__.constructor属性可以明确是由哪个构造函数创建出来的 49 50 //7.特殊情况需要手动把constructor属性指回来 51 // 如重新给prototype赋值,会造成constructor丢失 52 Dog.prototype = { 53 barking: function (){ 54 console.info('汪汪汪...') 55 } 56 } 57 // 因为重新给Dog.prototype赋值了一个对象 58 console.info(Dog.prototype.constructor === Dog) // false 59 60 // 手动把constructor属性指回来 61 Dog.prototype = { 62 constructor: Dog, 63 barking: function (){ 64 console.info('汪汪汪...') 65 } 66 } 67 console.info(Dog.prototype.constructor === Dog) // true 68 69 // 8.原型对象(prototype)的原型(__proto__) 70 // 原型对象也是对象,因此也因该有原型,即Dog.prototype.__proto__ 71 // 而这个原型对象的原型(Dog.prototype.__proto__)是Object构造函数的原型对象 72 console.info(Dog.prototype.__proto__ === Object.prototype) // true 73 // 也即是这个原型对象的原型的constructor属性(Dog.prototype.__proto__.constructor)为Object 74 console.info(Dog.prototype.__proto__.constructor === Object) // true 75 //这个原型对象的原型 的原型是null 76 console.info(Dog.prototype.__proto__.__proto__) // null 77 78 // 以上即是原型链
最后附上pink老师画的原型链示意图: