这篇文章主要讲解了“JavaScript中Function与Object的关系是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript中Function与Object的关系是什么”吧!
原型链
我们来回顾一下什么是原型
我们知道js中所有的对象、函数、数组都可以看成对象,也就是一切皆是对象
所有的对象身上都有一个
__proto__属性,他叫隐式原型,指向了构造这个对象(如obj)的构造函数(例如Constructor)的原型对象即Constructor.prototype,也就是说
obj.__proto__===Constructor.prototype,这两个指针指向的其实是同一块堆空间
在构造函数的原型对象prototype(
Constructor.prototype)中,一般包含
constructor属性和
__proto__属性。
其中
constructor包含函数的一些信息如
argments、
caller、
length、
name和prototype指向构造函数的原型对象自身以及
__scope__即闭包属性(其中有函数需要使用的外部变量以及全局上下文,以伪数组的形式储存在scope闭包对象中),另外
__proto__的话,其实就是把
Constructor.prototype看成
new出来的对象实例,
__proto__就是指向
Constructor.prototype的构造函数(如
Superconstructor)的实例对象即
Superconstructor.prototype
具体可以参照下图:
然后是原型链
由于对象(如obj)的隐式原型(
obj.__proto__)指向构造函数的
prototype(如
Constructor.prototype),
而这个
prototype(如
Constructor.prototype)里面又有一个
__proto__,它指向了
prototype的构造函数的
prototype(如
Superconstructor.prototype),
然后
Superconstructor.prototype.__proto__指向了
Object.prototype
这样就形成了一个简单的链式结构,这个条链的最后是
Object.prototype.__proto__为null
以上就是原型链的构成
原型链的使用
当你使用一个对象的属性或方法时,会先在该对象上查找已有属性,如果没有,就找到__proto__,找原型身上的属性,如果原型没有,那就再找原型的原型身上是否存在待查找属性,知道找到或者找到原型链的顶端null
关于原型链一些有意思的东西
我们知道
typeof可以用于判断变量的数据类型,但是对于复杂数据类型,它只能判断出对象、数组或函数,这对于我们的使用来说是不够的
所以我们可以用
instanceof来判断引用数据类型的对象类型
typeof A //'function' obj instanceof A //true obj instanceof Object //true
在使用时我发现一个有趣的问题
Function instanceof Object //true Object instanceof Function //true
这是为什么呢?
我们尝试使用
Function.__proto__===Object.prototype //false
发现得到的是false,也就是Function并不是Object new出来的
但是尝试
Object.__proto__===Function.prototype //true
却发现Object是由Function
new出来的
接着我们分析一下
instanceof的工作原理, 我们尝试用函数instance_of来手写
instanceof关键字
function instance_of(L, R) { var O = R.prototype; L = L.__proto__; while (true) { if (L === null) return false; if (O === L) return true; L = L.__proto__; } }
对于以上代码分析,我们其实是在找左值的原型链上是否存在右值的原型
于是我们尝试
Function.__proto__===Function.prototype //true Function.__proto__.__proto__===Object.prototype //true
发现原来
Function.prototype是由Object
new出来的,同时Function也是可以由自己
new出来
综上,
Function由Function
new出来,
Object由Function
new出来,
Function.prototype由Object
new出来
最后是关于new关键字
当代码
new Foo(...)执行时,会发生以下事情:
一个继承自
Foo.prototype的新对象被创建(类似于
Object.create)。
使用指定的参数调用构造函数
Foo,并将
this绑定到新创建的对象。
new Foo不带括号就是没有指定参数列表,
Foo不带任何参数调用。
由构造函数返回对象,作为
new表达式的结果。如果构造函数没有显式返回一个对象,则使用步骤 1 创建的对象。(一般情况下,构造函数不返回值,但是可以选择主动返回对象,来覆盖正常的对象创建步骤)
尝试用
newFun手写
new关键字
function newFun(Constructor) { var obj = {}; obj.__proto__ = Constructor.prototype; return Constructor.apply(obj); };
使用
Object.create
function newFun() { Constructor = [].shift.call(arguments);// 取出第一个参数Constructor var obj = Object.create(Constructor); return Constructor.apply(obj, arguments);// 使用参数调用 };
补充一点题外话
let a = { k:10, hh(){ console.log(this); } } let b = { k:9, a } b.a.hh();
使用对象链式调用hh()函数,它的this指向通过隐式绑定还是指向直接调用它的对象a,而不是间接调用的对象b