«

JavaScript中Function与Object的关系是什么

时间:2024-5-11 11:40     作者:韩俊     分类: Javascript


这篇文章主要讲解了“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

标签: javascript

热门推荐