前言
首先对象都有原型和原型链,通过原型链我们可以找到对象的"继承",可以通过原型链找到父类以及顶级 Object 的参数和方法,并且使用它们。在对象中又包含一个隐式原型(proto)和一个显式原型(prototype),构造函数通过 prototype 可以找到它们的原型,而实例函数可以通过 proto 找到它们的原型。
继承属性
JavaScript 对象是动态的属性“包”(指其自己的属性)。JavaScript 对象有一个指向一个原型对象的链。当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。
创建对象
创建对象一般有三种方法,字面量、构造函数、Object.create
第一种:字面量 var o1 = { name: 'o1' } var o2 = new Object({ name: 'o2' })
第二种:构造函数 var M = function(name) { this.name = name } var o3 = new M('o3')
第三种:Object.create var P = { name: 'p' } var o4 = Object.create(P)
构造函数和普通函数的区别
如果一个函数被 new 实例后,那么这个函数就是构造函数 一般构造函数的函数名首字母都要大写 构造函数中都会有自己的 this,而普通函数中的 this 是指向 window 的
构造函数、实例函数、原型对象、原型链
构造函数:
创建一个函数并且该函数被 new 实例化过
实例函数:
通过 new 实例化一个函数
原型对象:
构造函数的原型,可以在上面新增一些属性和方法
原型链:
实例可以通过 proto 拿到构造函数的原型
它们之间的关联
这里的核心人物就是构造函数,它可以使用 prototype 获得它的原型,而原型可以通过 constructor 指回构造函数,也可以使用 new 创建一个实例,实例可以通过 proto 获取构造函数的原型,而该构造函数的原型对象你可以看作是父类函数的一个 实例函数 关系如下图:
instanceof的原理
instanceof 用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上,我们知道 typeof 是判断数据类型的,但是它判断不了 Object 类型的继承,所以我们可以使用 instanceof 进行判断,判断某个实例对象是否在对象的原型链上。 但是 instanceof 也有不严谨的地方,它无法分辨判断出来的结果是否是它本身的构造函数,所以想要更精准的判断可以使用 实例对象.proto.constructor === 构造函数
new 运算符
一个新对象被创建,它继承自 foo.prototype 构造函数 foo 被执行:执行的时候,相应的传参会被传入,同时上下文(this)会被指定为这个新实例。new foo 等同于 new foo(),只能用在不传递任何参数的情况 如果构造函数返回了一个"对象",那么这个对象会取代整个 new 出来的结果,如果构造函数没有返回对象,那么 new 出来的结果为步骤1创建的对象