你应该知道的冷知识
- 每一个函数都有一个
prototype(原型)属性,属性值是一个普通的对象 - 每一个对象都有一个
__proto__(隐式原型)属性,指向他构造函数的(原型prototype) ,即会从原型“继承”属性 - 函数也是一个对象,所有的函数都来自于构造函数Function
- 所有的对象都可以从原型链追溯到Object,并且Object也是一个构造函数
- 每个原型都有一个
constructor属性,指向该关联的构造函数。
原型链的小概念
当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链
例子1、原型链
//构造函数
function Parent(name,age){
this.name = name
this.age = age
}
var child = new Parent('张三',30)
console.log(child)
console.log(child.__proto__)
console.log(Parent.prototype)
console.log(child.__proto__ === Parent.prototype) //true
//打印数据展示
由此可以看出,新的child对象在生成的时候会自带一个隐式原型 __proto__ 指向构造函数Parent 的 prototype,而且prototype下面存在一个constructor指向构造函数函数本身,如果Parent函数再根据原型链往下寻找,会找到Object()函数,如下图
Parent.prototype.height = '180cm'
//这里会打印180cm,就是child通过原型链找到的属性值
console.log(child.height) // 180cm
本次创建child对象的原型链可如下图所示:
new对象干了什么坏事?
- 创建(或者说构造)一个全新的对象
- 这个全新的对象会被执行[[prototype]]连接:当前对象的__proto__ 指向构造函数的 prototype
- 这个新对象会被绑定到函数调用的this
- 如果函数没有返回其他对象,那么new表达式中的函数会自动返回一个新对象
function Foo(name){
this.name = name
}
var foo = new Foo('小明')
//解析new执行步骤
//1、创建新对象
var obj = {}
//2、[[prototype]]连接
obj.__proto__ = Foo.prototype
//3、this指向转换
var foo = Foo.call(obj, '小明');
// 返回对象(前提是构造函数为返回其他对象)
return foo
Function 与 Object 的恩怨!
//你中有我,我中有你
console.log(Function instanceof Object) //true
console.log(Object instanceof Function) //true
先根据顶部冷知识思考
1、Function,Object 都是构造函数,所以既有 __proto__ 又有 prototype,只是指向问题,所以打印一下
//Function的原型对象
console.log(Function.prototype);
//Object的原型对象
console.log(Object.prototype);
//Function的原型对象的原型对象
console.log(Function.prototype.__proto__);
console.log(Object.prototype === Function.prototype.__proto__);
Function 与 Object 错综复杂的关系。
小结一下:
可以说是Function自己生了对象,生了函数,还生了自己....
Object作为他生的函数有了
Object.__proto__ === Function.prototype
但是又有
Function.__proto__===Function.prototype
这里形成了环形结构,即所谓的原型链。导致Object.prototype成为了没人要的野孩子,所以为null了
转一张别个绘制的图,看一看突然就懂了: