首先你需要对 JS 有一定了解,其次,我们开始吧
__proto__
首先说一下这个 __proto__ 属性,说明一下这个属性不要去访问,而且这个属性后期会被遗弃掉。这不是我说的,这是万能的 MDN 说的。
虽然说这个东西会被废弃掉,但是身为一名合格的前端人员还是需要知道一下的。
举个栗子:
function A() {};
const aFn = new A();
此时这个变量的 aFn 的 __proto__ 就会指向 A 函数的 prototype,对没错,它就是这么简单,说的天花乱坠的它其实就是指向实例化的函数的 prototype (验证一下 aFn.__proto__ === A.prototype 返回为 true)
那么接下来就说一说这个 prototype。
prototype
首先声明一下,这个属性只会出现在 函数(Function) 上。
当然了对象上也可以有,比如:
const obj = {};
obj.prototype = {};
这样是无意义的奥,为什么?首先你需要明白函数上有这个东西是干嘛用的?
刚开始呢设计函数的人是这样想的
// 他创建了一个猫
const cat = {}
cat.name = '大黄'
cat.color = '黄色'
// 又创建了一个狗
const dog = {}
dog.name = '大黄'
dog.color = '黄色'
// 他还想创建一个鸡
// 他还想创建一个鸭
// 他还想创建一个...
是不是感觉太麻烦了吧!然后他就设计了下边这个
// 这里有一个动物的构造函数 Animal
function Animal(name, color) {
this.name = name;
this.color = color;
}
// 设计他的人希望创建 猫 或者 狗 的时候能方便一点
const cat = new Animal('大黄', ‘黄色’)
const dog = new Animal('小黄', ’蓝色‘)
已经很好了,但是有这样一个需求,要创建 N 个狗,狗的名字和颜色不一样。但是叫声是一样的。然后他就设计了这样写
function Dog(name, color) {
this.name = name;
this.color = color;
this.say = function() {
console.log('wang ~')
}
}
const dog1 = new Dog('狗一', 'red');
const dog2 = new Dog('狗二', 'pink');
const dog3 = new Dog('狗三', 'blue');
但是产品说,狗见到不同的人叫声不同,见到主人,它会叫 wo ~, 见到陌生人 它 才会叫 wang ~
啧... 那现在我该如何去修改这个 say 方法呢?所以他想到了 prototype,让所有的狗去继承这个方法
function Dog(name, color) {
this.name = name;
this.color = color;
}
Dog.prototype.say = function() {
console.log('wang ~')
}
const dog1 = new Dog('狗一', 'red');
const dog2 = new Dog('狗二', 'pink');
const dog3 = new Dog('狗三', 'blue');
这样一来 需要修改所有狗的 say 方法的时候 只需要修改 Dog.prototype.say 就可以了
dog1.say() // wang ~
Dog.prototype.say = function() { console.log('wo ~') }
dog1.say() // wo ~
那么我们可以这样理解
所有”私人“的属性都应该在构造函数内部调用(new Function)的时候定义,公共的方法和属性应该放在原型链上。
比如 dog1 和 dog2 和 dog3 的名字都是不一样的,那么名字就需要在构造函数内部调用的时候定义。
但是 dog1 和 dog2 和 dog3 都是狗,他们的类型都是狗,那么就应该在 Dog 的构造函数上定义 Dog.prototype.type = '狗'。
just soso easy! 可能我的栗子举得不是很好,但是希望你能看懂