js中所有数据类型其实都是Object的“孩子”。包括字符串,函数,布尔值等等,只不过这些数据类型被解析器进行了包装,包装成了我们现在看到的这些数据类型的样子(字面量), 但是我们需要知道其本质都是对象,所以每一个数=数据类型都是可以使用,取消,同时也都是new出来的
- 声明一个空对象obj let a = {} 这里声明的是一个真正意义上的空对象,那就是null
- 将fun的prototype属性浅复制给obj的--proto--属性
- obj._protr_=fun.prototype
- 所有函数都有prototy属性(原型对象)
- 所有对象都有_proto_属性(对象的原型)
- 浅复制给obj._proto_属性到底是为什么
- 因为是浅复制,所以obj._proto_和fun.prototype共用一个地址
- 可以将一些内容放在这个函数的prototype(是个对象)属性中,通过这一步的机制,可以巧妙的传递给该函数创造出的对象,并且又因为两个属性共用一个地址,这样既可以节约内存也可以让对象获取到prototype中的内容,从而使对象中的内容更充实和强大
- new一个函数可以得到一个对象,我们称这个函数为一个对象构造器,也就是构造函数,它与其他函数并无区别,就是因为被new了,所以被称为构造函数
- MDN文档中写的都是Array.prototype.flat等等类似标题,因为每一个数组都是new Array得到的,所以每一个数组都可以通过_proto_属性获取到Array函数的prototype属性中的内容,没这样的标题表示这些功能函数都是存放在构造函数的prototype中的
- 构造函数中prototype属性中都有一个属性constructor,在对象的_proto_中也就有了constructor属性,这个属性就是构造函数的克隆,这样我们就可以通过对象观察其_proto_中的内容就可以发现,这个对象的构造函数是谁
- 上一条说:每一个对象都可以通过_proto_获取到其构造函数中的prototype中的内容,但是我们从未使用[]._proto_.push(),都是直接[].push(),
- 这是因为原型链
- 原型链是一种寻值机制,这种寻址机制的触发依靠成员访问符。或者方括号
- 对象.属性会先在该对象自身属性中寻找是否有该属性,如果没有那就自动向其_proto_属性中寻求是否有该属性,如果还没有(_proto_也是一个对象,所以它也有_proto_)那就继续寻找其_proto_中的_proto_中寻找是否有该属性...一直寻找到null
- 原型链的作用:节约内存
- 改变this指向,改为指向obj let func = func.bind(obj) --- 也正是因为这一步,所以构造函数中的this指向是new得到的对象
- 正常执行fun函数 也就是新函数func fun()
- 返回obj return obj
- 如果构造函数本身的返回值是非对象 那么被new之后返回这个新对象也就是上面的obj
- 如果构造函数本身的返回值是对象(returnObj),那么new之后返回的内容是这个构造函数本身的返回值,也就是returnObj
new 关键字的优先级
优先级高 new(带参数列表) new ... ( ... )
优先级低 new(不带参数列表) new ...