本文是笔者在备战秋招时总结所得,如有错误,欢迎指正,一起学习~~~
原型链
首先你需要清楚:
-
所有函数类型都天生具有**prototype(原型)**属性。
-
prototype中有一个constructor属性,这个属性就是指向当前构造函数本身。
其实这个属性指向了**[[prototype]],但是 [[prototype]] 是内部**属性,我们并不能访问到,所以使用
_proto_
来访问。 -
每一个对象都有一个
_proto__
属性,这个属性指向其构造函数的prototype (原型)obj.__proto__ = Constrcutor.prototype;
原型链是基于proto向上查找的机制,当我们要查找一个实例对象的某个属性或者方法时,我们会先在其私有的空间上查找,若无,则会查找基于proto所属类的prototype,若无,再向上查找,直到最后找到Object.prototype, 再向上直到null。
也就是: obj -> obj.proto->obj.prototype.proto -> ...-> Object.prototype -> Object.prototype.proto ->null
扩展原型链的几种方法:
-
Object.setPrototypeOf(obj, newobj)
-
obj.prototype =
-
let obj = Object.create(foo.prototype)
(创建一个对象 并将原型链指向foo.prototype)
- obj. proto=
obj.[[Prototype]] 用于指向 obj 的原型
[[Prototype]] 从es6开始可以通过 Object.getPrototypeOf() 和 Object.setPrototypeOf() 来访问,等同于 __proto__
。
被构造函数创建的实例对象的[[Prototype]] 指向 func 的 prototype 属性。
继承
继承是基于原型链的继承,分为继承属性和继承方法。
function inherit(parentConstructor, prototypeObj) {
function Cat(...args) {
// 继承属性
// 将Animal的this指向 cat1实例 => 继承了Animal
parentConstructor.apply(this, args);
}
Cat.prototype = prototypeObj;//实例cat1的proto
// 继承方法
// Object.setPrototypeOf(Cat.prototype, parentConstructor.prototype);
Cat.prototype.__proto__ = parentConstructor.prototype
// 将Animal.prototype设置给Cat.prototype
return Cat
}
let animalNum = 0;
// 属性
function Animal(name,size) {
animalNum++;
this.size = size
this.name = name;
}
// 方法
Animal.prototype.getName = function () {
return this.name;
};
const Cat = inherit(Animal, {
say: function () {
console.log(`NO${animalNum}:${this.getName()}`);
}
});
const cat1 = new Cat('小花',10);
console.log(cat1)
cat1.say(); // NO1:小花
instanceof
检测构造函数的protype是否在某个实例对象的原型链上。
function instance_of(L, R) {
let O = R.prototype;
L = L.__proto__;
while (true) {
if (L === O) {
return true;
} else if(L.__proto__ === null) {
return false
}
L = L.__proto__;
}
}
new
实现new的过程,伪代码如下:
-
创建一个继承自Object.prototype的空对象
-
继承原型对象
-
将这个对象作为构造函数要运行时的this 作用:增加原型的属性给自身
-
返回结果, 若构造函数的返回值为基本数据类型,则忽略,若为引用数据类型,则直接返回这个对象。
1.0(此为简单版本,未考虑new的传参问题)
function myNew(Constructor) { // 1 创建一个 继承自构造函数 Object.prototype 的对象 let obj = {} // 继承 原型对象 obj.__proto__ = Constructor.prototype; // 2 这个对象 作为构造函数运行时的 this,作用:增加原型的属性到自己的属性上 let res = Constructor.apply(obj) // let res = obj console.log(res) // 3 new 产生的结果: 3.1 如果构造函数返回一个对象了, new 结果就是这个对象 // 3 new 产生的结果: 3.2 如果构造函数没有返回一个对象, new 结果就是我们刚才创建的这个对象 // console.log(obj.hosts); // todo 3 return typeof res === 'object' ? res : obj; } function Animal() { // return { // a:1, b:2 // } // 如果 返回的不是一个对象, return 对 new 的结果没有任何作用 // return 3; this.name = 'cat'; } let ani = new Animal(); console.log(ani);
2.0 (传参版本)
function _new (Constructor, ...args) { let obj = Object.create(Constructor.prototype); let res = Constructor.apply(obj, args) return typeof res === "object" ? res : obj } function _Animal(name, size) { this.name = name, this.size = size } let cat = _new(_Animal, 'cat', 10)