首先,明确两点
- JS所有对象(包括函数)都是
Object的实例
,并继承Object.prototype
的属性和方法;
// 普通对象
const obj = {};
console.log(obj instanceof Object); // true
// 箭头函数
const myFun = () => {};
console.log(myFun instanceof Object); // true
// 函数表达式
const myFun2 = function() {};
console.log(myFun2 instanceof Object); // true
Object
对象主要的属性和方法举例:constructor
属性:保存当前对象的构造函数hasOwnProperty(propertyName)
方法:判断该属性是否在当前对象实例
中,而不是在对象的原型链中isPrototypeOf(Object)
方法:判断当前对象是否在传入的参数对象的原型链上Object.prototype.isPrototypeOf(obj)
propertyIsEnumerable(prototypeName)
方法:判断给定的属性是否可以被for..in
语句给枚举出来(比如constructor属性就不行)toLocaleString()
方法toString()
方法valueOf()
方法
- 对象在创建时,会有一些预定义的属性。定义
普通对象
时,会生成一个__proto__
,它指向这个对象的构造函数的prototype
。在定义函数时,会生成一个prototype
,它同样是一个普通对象,里面包含指向构造函数的constructor
以及一个__proto__
,这个__proto__
同样会指向这个函数的构造函数的prototype
(一般为顶层Object,Object.prototype
同样有一个__proto__
,其值为null
)
JS数据类型有:
基本数据类型
:String,Number,Boolean,Null,Undefined,Symbol
引用数据类型
:Object,Array,Function
Array.prototype
是一个数组,arr.__proto__
同样是一个数组(其中,arr是Array的实例)
例如:
const fn = function(x) {
this.x = x;
};
console.log(fn.prototype.__proto__ === Object.prototype) // true
console.log(Object.prototype.isPrototypeOf(fn)); // true
console.log(fn instanceof Object); // true
// 实例化一个对象
const obj = new fn("123");
console.log(obj.__proto__ === fn.prototype) // true
解释下原型链
:我们其实可以通过obj.toString()
调用该方法,原理其实是,先会在obj
这个对象上找有没有toString()
方法,没有的话去obj.__proto__
也就是fn.prototype
上找,而在这个例子里也没有,那就沿着fn.prototype.__proto__
向上找,就相当于Object.prototype
,如果也没找到那就没有。
回过头来解释一下,为什么JS所有对象都是Object实例?
// 定义一个函数并实例化一个对象
const fun = function() {
console.log("执行fun函数");
};
const obj = new fun();
console.log(obj instanceof fun) //true
console.log(obj instanceof Object) //true
console.log(fun instanceof Object) //true
- 第一个结果分析:
obj
是对象,创建时会生成一个__proto__
,它指向的是这个对象的构造函数的prototype
,即fun
函数的prototype
(fun
是一个函数,定义函数时会生成一个预定义属性prototype
) ,执行obj instanceof fun
相当于判断obj.__proto__ === fun.prototype
是否正确; - 同样,
fun
函数的prototype
也是一个对象,fun.prototype
里面包含构造方法constructor
以及__proto__
;类似的,由于所有对象都是Object的实例,所以fun.prototype.__proto__
指向的是构造函数,即最顶层Object的prototype
。而instanceof
在多层继承关系中同样有效,也就是说__proto__
会一直向下传递,一直找到原型链的尽头。 - 而原型链的尽头是
Object.prototype.__proto__ === null
console.log(fun.prototype.__proto__ === Object.prototype) //true
instanceof
用于判断一个变量是否某个对象的实例;
object instanceof constructor
=> 检测constructor.prototype
是否在object的原型链
上;在多层继承
关系中,instanceof也同样适用
最后,我写的其实比较烂,当是学习笔记。推荐阅读我的一个大佬朋友的文章彻底弄懂原型与原型链