1. 原型对象和构造函数纠缠不清的一生
// prototype 函数类型的数据,都有一个叫做 prototype 的属性。 // 这个属性指向的是一个对象,就是所谓的原型对象。 function fn() {} fn.prototype; // { constructor: f } 这个就是原型对象 // constructor 属性指向它的构造函数 fn == fn.prototype.constructor; // true
2. 原型对象的作用
最主要的作用就是用来存放实例对象的公有属性和方法,不然每次创建实例,相同的属性和方法都会重复创建,浪费内存。
function Person(name, age) { this.name = name; this.age = age; } Person.prototype.type = "people"; Person.prototype.say = function () { console.log("呀食勒没啊"); }; // 实例对象在自己这找不到对应的属性和方法,就会去构造函数的原型对象找。 // 如果有,就返回。如果没有,就会沿着__proto__继续往父级找,直到为null为止 let yqcoder = new Person("yqcoder", 18); yqcoder.type; // people yqcoder.say(); // 呀食勒没啊 yqcoder.constructor; // 查看对象的构造函数 Person() {}
3. 原型链
// prototype 显示原型,这是函数类型数据的属性,指向原型对象 // __proto__ 隐式原型,这是对象类型数据的属性,指向原型对象 Person.prototype == yqcoder.__proto__; // true // 实例对象如果顺着__proto__属性一直往父级的原型对象找,都没找到就返回undefined。 // yqcoder.__proto__.__proto__.__proto__ 这种结构就叫原型链,也叫隐式原型链。 // 它的终点就是Object.prototype指向的原型对象,下一个__proto__就为null了 yqcoder.love; // undefined
4. 万物皆对象
// 函数也是对象,那么函数也有__proto__指向原型对象。 // 原型对象里的constructor指向构造函数Function Person.__proto__ == Function.prototype; // true
5. 总结
术的尽头,气体源流
原型的尽头,Object.prototype