1. 创建对象有几种方法
// 1. 字面量
var o1 = { name: 'o1' }
var o2 = new Object({ name: 'o2' });
// o2 也可看作时构造函数
// 构造函数
var M = function (name) {
this.name = name;
}
var o3 = new M('o3M')
// 3. Object.create()
var p = {name:'p'}
var o4 = Object.create(p)
// o4是直接拿不到name属性的
//
2. 原型、构造函数、实例、原型链

- 只要是对象就是实例
- 只要是用new来操作的都是构造函数
- 构造函数可以使用new运算符生成一个实例
- 函数都有一个prototype属性(申明一个函数时js自动加上的属性)
- prototype属性会初始化一个空对象---原型对象
- 原型对象如何区分被哪一个构造函数所引用:原型对象中会有一个构造器(constructor),这个构造器会默认你申明的那个函数
- 实例对象有__proto__属性(函数也有__proto__属性)
例1
// 构造函数
var M = function (name) {
this.name = name;
}
var o3 = new M('o3M')
o3是创建的一个实例对象
M是构造函数


对象有一个__proto__属性,指向构造函数的原型对象

所以构造函数、实例、原型对象的关系为:
- 构造函数通过new和实例关联,
- 构造函数的原型对象通过constructor和构造函数相关联
- 实例的
__proto__属性指向构造函数的原型对象
原型链
从一个实例对象往上找构造这个实例的相关的对象,然后这个关联的对象再往上找,他又有创建它的上一级的原型对象,以此类推,一直到Object.protopyte原型对象终止,这个链条就断了。也就是说Object.protopyte属性是整个原型链的顶端
在访问一个实例或者他上面的方法的时候,如果在实例本身没有找到这个方法和属性的时候,就通过
__proto__属性从实例的原型对象上找,如果上一级对象上还没有找到,再从原型对象的基础上,再通过__proto__属性再往上一级查找,以此类推,知道找到直到Object.protopyte,若还未找到,则没有这个方法,原路返回。
原型链是通过prototype这个原型对象和__proto__属性来完成原型链的查找
原型对象和原型链之间的起了什么样的作用:当构造函数中写了多个属性和方法,实例是不是就可以公用这个东西了/当有多个实例的时候,想去共用这个方法的时候,可以存到一个共同的东西上(原型对象)
var M = function (name) {
this.name = name;
}
var o3 = new M('o3M')4
// 通过再M的原型链上增加方法
M.prototype.say = function () {
console.log('say hi')
}
let o5 = new M('o5')

通过原型链的方式,找到原型对象,原型对象上的方法是被不同的实例所共有---原型链的工作原理
3. 原型链类之instanceof 的原理
原理:判断实例对象的
__proto__属性和构造函数的prototype属性是不是同一个引用地址。
检测基本数据类型时用typeof,检测引用数据类型是什么类型的对象时用instanceof 如果使用 instanceof 操作符检测基本类型的 值,则该操作符始终会返回 false,因为基本类型不是对象。

只要是在这个原型链上的构造函数,都会被
instanceof看作是实例对象的一个构造函数
比如a继承了b,b继承了c。a生成的实例对象,用instanceof判断b或c,返回的都是true。


为了严谨,使用constructor来准确判断到底是a还是b、c生成的实例
