函数对象、函数原型对象、函数实例对象的关系
作者:wangYaLo;
CSDN:你多喝点水
GitHub:wangYaLo
先来说一下
//先说一下__proto__和prototype的关系
首先,js
代码还没有运行的时候,js
环境里面有一个window对象
第二,这个window对象有一个Object属性;
第三,window.object
这个函数对象有一个重要的属性prototype,
第四,window.Object.prototype
里面有toString()
、valueOf()
然后执行下列代码
var obj = {};
obj.toString();
为什么这个obj上面有这个属性?
其实就是创建obj对象的时候会给予一个__ proto __
的属性,这个属性指向window.Object.prototype
这样的话,在obj
调用toString
的时候就会沿着 __proto__
找到toString
这个方法,
也就是说,obj.toString()
等价于 window.Object.prototype.toString()
;
然后就是 window.Object.toString()
是怎么获取到obj的内容的;
首先 obj
获取内容等方法是 obj.toString.call(obj)
,那就是说window是通过 window.Object.toString.call(obj)
获取到 obj
的内容的。
然后
var obj = {}
//也等于
var obj = new Object();//也是创建了一个空的对象
也就是说obj的__proto__
指向创建他的对象的prototype;
首先我们创建了一个函数
function Func() {
console.log(this)
}
new Func(); //Func {}
当我们创建了一个函数,我们叫这个函数为函数对象,当我们new这个函数的时候,我们把new Func()
这一个东西叫做函数的实例对象,
而这里的new操作符做了什么呢?
new操作符是js的一个语法糖,我们可以理解为
//有一个new函数
function new(func, ...arg) {
//func就是我们new 的对象,
//首先,new操作符会创建一个空对象;
var obj = {};
//每当我们创建了一个函数的时候,会为这个函数创建一个prototype属性
//然后把这个空对象的的__proto__指向func的prototype
obj.__proto__ = func.prototype;
//然后把func的this指向指向obj,并将其他参数传入;
let result = func.apply(obj, arg);
//函数可以没有返回值也可以有返回值,所以要判断有没有返回值,如果没有返回值的话也就是说返回值默认为undefined,有的话会判断返回值是否为对象,如果是的话会指向对象,如果不是的话会指向obj;
return result instanceof Object ? result : obj
}
我们举个例子说明一下函数有无返回值的情况
//no return
function Func(){
console.log(this)
}
console.log(new Func()); //is {}
//return no Object
function Func() {
return 1
}
console.log(new Func()); //is {}
//return Object
function Func() {
return { name: 'lisi' };
}
console.log(new Fun()); //is { name: lisi }
回到我们创建构造函数
function Func() {
console.log(this)
}
new Func()
当我们创建这个函数的时候,会给这个函数添加一个prototype的属性,也就是他的原型;
这个prototype
里面有一个属性constructor
;这个属性指向的是一个指向prototype所在函数的指针;
也就是说指向的是Func
,并且执行这个函数内的方法;
//通过console.log(Func.prototype.constructor)
function Func() {
console.log(this)
}
console.log(Func.prototype.constructor);//is f Func() { console.log(this) };
当我们对他进行new的时候;
//我们现在知道this会指向我们新建的对象;
function Func() {
this.name = 'lisi';
this.age =18;
}
cosnt p = new Func()
//然后通过constructor执行我们Func的函数,this指向我们新创建的空对象,通过执行函数给空对象添加属性;
console.log(p); //{ name: 'lisi', age: 18 }
而这个通过new出来的对象,我们叫做实例对象;刚刚我们在上面可以看到obj.__proto__=Func.prototype
,也就是说p的隐式原型指向构造该对象的构造函数的原型,也就是说 p.__proto__ = Func.prototype
我们现在可以得出结果
Func
通过new
创建了p
, 那么p
的 __proto__
指向了 Func.prototype
, Func.prototype
里面有constructor
属性可以访问到Func
函数