javaScript原型和原型链的详细介绍网上已经有很多大神文章介绍过,本篇不打算再讲原理。如果朋友您已经理解了原型、原型链兴许这边文章能起到一点点作用。
说实在的我在实际工作中很少用到原型链,顶多在自建的对象原型上或者预定义对象原型上(比如Array.prototype)添加个方法,但我又一直记不住原型链。在学习总结之后,我我决定把种种特例拆开来记忆,就像小学学习乘除法时将0和1特殊记忆。
必须了解的概念
1、只有函数才有prototype属性
2、所有对象都有_ _ proto _ _属性,它不是ECMA规范定义的,但绝大部分浏览器都实现了
3、JavaScript中万物皆对象,函数也是对象,所以函数既有prototype又有_ _ proto _ _属性
4、一个对象的_ _ proto _ _属性指向它的构造函数的prototype(原型),将这句话带入图中就更好理解和记忆
不同类型的对象原型链图
1、Object对象
let a = { name:"小明",age:20 }//通过字面量创建的对象
let b = new Object()//通过构造函数创建的对象
这类Object对象的原型链最简单,如下图:
Object对象的原型链
2、Function对象
let c = function() {}//函数表达式
let d = new Function()//通过构造函数创建的函数
这类的Function对象的原型链:
Function类型的对象的原型链
3、其他对象
let e = new Array()//预定义类型的对象
class Cat {
constructor(){}
}
let f = new Cat()//通过其他function new出的对象
其他自定义、预定义类型的对象的原型链
最后两个图中,从typeof Function.prototype === function可以看出Function.prototype也是一个函数对象,所以它也有prototype属性,而它的prototype属性是undefined,也是特殊的一个地方
下面是具体的实验:
class Cat {
constructor() {
}
}
let mycat = new Cat();
console.log("1-1:", mycat instanceof Cat);
console.log("1-2:", Cat.prototype);
console.log("1-3:", Cat.__proto__);
console.log("1-4:", mycat.__proto__);
console.log("1-5:", typeof Cat.prototype);
console.log("1-6:", Cat.__proto__ === Function.prototype);
console.log("1-7:", Object.prototype === Cat.prototype.__proto__);
console.log("1-8:", Cat.prototype.constructor === Cat);
console.log("1-9:", mycat.__proto__ === Cat.prototype);
let a = {};
console.log("2-1:", a.__proto__);
console.log("2-2:", a.prototype);
console.log("2-3:", a.__proto__ === Cat.prototype.__proto__);
console.log("2-4:", a.__proto__.__proto__);
let b = new Object();
console.log("3-1:", b.__proto__);
console.log("3-2:", b.__proto__ === Object.prototype);
console.log("3-3:", b.__proto__ === Cat.prototype.__proto__);
console.log("3-4:", b.__proto__.__proto__);
let c = function(arg1, arg2) {
let cc = "hello";
};
console.log("4-1:", c.__proto__);
console.log("4-2:", c.prototype);
console.log("4-3:", c.__proto__ === Function.prototype);
console.log("4-4:", c.__proto__.__proto__ == Object.prototype);
console.log("4-5:", c.__proto__.__proto__.__proto__);
let d = new Function();
console.log("5-1:", d.__proto__);
console.log("5-2:", d.prototype);
console.log("5-3:", d.__proto__ === Function.prototype);
console.log("5-4:", d.__proto__.__proto__ == Object.prototype);
console.log("5-5:", d.__proto__.__proto__.__proto__);
console.log("5-6:", Function.__proto__ === Function.prototype);
console.log("5-7:", Function.prototype.__proto__ === Object.prototype);
let e = new Array()
console.log("6-1:", e.__proto__);
console.log("6-2:", e.__proto__ === Array.prototype);
console.log("6-3:", e.__proto__ === Cat.prototype.__proto__);
console.log("6-4:", e.__proto__.__proto__);
console.log("7-1:", typeof Function.prototype);
console.log("7-2:", typeof Object.prototype);
console.log("7-3:", Function.prototype.prototype);
实验结果
在chrome里Function.prototype通过console.log()打印是出来的是
f(){[native code]}
其实就是Function.prototype.toString()的结果,是 native 的代码实现的 built-in 函数,而不是 JavaScript 代码。但这并不是语言标准规定的,只是恰好 Chrome 都这么做了,不过这里不需要关心~。
网友评论