前言:在我们平常工作中,我们常有人说JavaScript中,“万物皆对象”。在弄懂原型和原型链之前,我们要知道它们是什么东西。
1.原型
首先,JavaScript 是基于原型继承(Prototypal inheritance)的语言。原型(prototype)是给其他对象提供共享属性的对象,每个函数都有一个 prototype 属性,它指向的是一个 prototype 对象,这个对象就是我们所说的原型。 例如:
let obj = {}
obj.__proto__ //输出如下图
这个obj.proto 就是obj的原型。
2.原型链
每个对象都有一个隐式引用([[Prototype]]),并且 [[Prototype]] 指向它的原型对象,并从中继承数据、结构和行为。同时原型对象同样拥有原型(函数也是对象,它也有[[Prototype]]),这样一层一层,最终指向 null,这种关系被称为原型链。 例如:
let obj = {};
console.log(Object.prototype === obj.__proto__); // true
这个指向关系就是我们所说的原型链。
在开始整活之前,我们要明确两点:
__proto__和constructor是对象独有的。prototype是函数独有的。- 在JavaScript中,函数也是对象,因此函数也拥有
__proto__和constructor。
开始整活了!!!
function Person() {}
let nealyang = new Person();
console.log(nealyang.__proto__ === Person.prototype); // true
console.log(Person.prototype.constructor === Person); // true
console.log(nealyang.__proto__.constructor === Person); // true
console.log(nealyang.constructor === Person); // true
console.log(Person.__proto__ === Function.prototype); // true
console.log(nealyang.__proto__.constructor.__proto__ === Function.prototype); // true
console.log(Function === Object.__proto__.constructor); // true
console.log(Function.prototype === Function.__proto__); // true
console.log(Function.prototype === Function.__proto__); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__ === null); // true
关系图:
注图片来源作者:Neal_yang,为方便读者理解,代码也采用nealyang定义
有了以上这些知识点,我们就可以探讨一下instanceof和new的一些相关原理。
3.instanceof
3.1 原理
instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上。例如:a instanceof b实际上是就是判断b.prototype是不是在a的原型链上。
代码如下
function foo() {}
obj1 = {};
console.log(obj1 instanceof foo); // false
obj1 = foo.prototype;
console.log(obj1 instanceof foo); // false
obj1.__proto__ = foo.prototype;
console.log(obj1 instanceof foo); // true
4.附录
4.1 typeof
let num = 1;
let obj = {};
let fun = () => {};
let str = "";
let arr = [];
let data = new Date();
let bool = false;
console.log(typeof num); // number
console.log(typeof obj); // object
console.log(typeof fun); // function
console.log(typeof str); // string
console.log(typeof arr); // object
console.log(typeof data); // object
console.log(typeof bool); // boolean
console.log(typeof null); // object
console.log(typeof undefined); // undefined
可以看见的是,引用数据类型中,除了function之外,其他的引用类型都会被判断为object,还有就是null会被判断为object。
4.2 利用原型链来判断数据类型
我们可以通过原型链来判断一个变量是什么数据类型,例如:
let num = 1;
let obj = {};
let fun = () => {};
let str = "";
let arr = [];
let data = new Date();
let bool = false;
console.log(Object.prototype.toString.call(num).slice(8, -1)); // Number
console.log(Object.prototype.toString.call(obj).slice(8, -1)); // Object
console.log(Object.prototype.toString.call(fun).slice(8, -1)); // Function
console.log(Object.prototype.toString.call(str).slice(8, -1)); // String
console.log(Object.prototype.toString.call(arr).slice(8, -1)); // Array
console.log(Object.prototype.toString.call(data).slice(8, -1)); // Date
console.log(Object.prototype.toString.call(bool).slice(8, -1)); // Boolean
console.log(Object.prototype.toString.call(null).slice(8, -1)); // Null
console.log(Object.prototype.toString.call(undefined).slice(8, -1)); // Undefined