new这个操作做了什么?
var p = new Person()
1.创建一个空对象(var obj = new Object())
2.将空对象的原型赋值给构造函数的原型(Person.prototype = obj.proto)
3.执行构造函数的代码,为空对象添加属性(Person.call(obj)),也可以理解为将构造函数内部的this指向新建的空对象
4.new调用的函数会自动的返回一个创建好的新对象
1.原型
var obj = new Object();
每创建一个对象的的时候,都会给它关联另一个对象(原型),都会从原型中“继承”属性
2.prototype(函数属性)
所有函数都会有一个prototype属性,这个属性指向函数的原型(通过bind()绑定的没有)
基于原型链的继承:A.prototype=new B();A继承B
3.__proto__(浏览器属性)
是所有对象(除null外)都有的属性,这个属性指向该对象的原型,
4. __proto__和prototype的区别:
__proto__是实例指向原型的属性
prototype是对象或者构造函数指向原型的属性
5.constructor
每个原型都有一个constructor属性,指向该关联的构造函数
cat1.constructor === Animal
每一个对象都会从原型中“继承”属性,cat1中并没有属性constructor ,但是它的原型cat1.__proto__ 指向的是Animal.prototype,然而Animal.prototype原型中是有属性constructor的,于是cat1的constructor属性继承与原型中的constructor属性。这里便能看出一点点原型链的影子了
6.原型的原型
Object.prototype.__proto__===null
即 Object.prototype 没有原型,在原型链中,当属性找到顶层原型都没有属性那就是没有这个属性
7.原型链
申明一个对象,var obj = { name: 'obj' } ,通过console.dir()打印一个对象的所有属性和方法的时候发现已经有valueOf / toString / constructor的属性/方法了,但是我们并没赋值啊,console.dir(obj) 打出来的结果是:
1. obj 本身有一个属性 name(这是我们给它加的)
2. obj 还有一个属性叫做 __proto__(它是一个对象),这个对象有很多属性,包括 valueOf、toString、constructor 等
3. obj.__proto__ 其实也有一个叫做 __proto__ 的属性(console.log 没有显示),值为 null
当我们「读取」 obj.toString 时,JS 引擎会做下面的事情:
1. 看看 obj 对象本身有没有 toString 属性。没有就走到下一步。
2. 看看 obj.__proto__ 对象有没有 toString 属性,发现 obj.__proto__ 有 toString 属性,于是找到了
所以 obj.toString 实际上就是第 2 步中找到的 obj.__proto__.toString。
可以想象,
3. 如果 obj.__proto__ 没有,那么浏览器会继续查看 obj.__proto__.__proto__
4. 如果 obj.__proto__.__proto__ 也没有,那么浏览器会继续查看 obj.__proto__.__proto__.proto__
5. 直到找到 toString 或者 __proto__ 为 null。
上面的过程,就是「读」属性的「搜索过程」,而这个「搜索过程」,是连着由 __proto__ 组成的链子一直走的,这个链子,就叫做「原型链」,当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层为止。这样就形成了原型链
注意:
故意创建不具有典型原型链继承的对象(通过Object.create(null)创建的对象)
改变原型链(通过Object.setPrototypeOf)