JavaScript基础: Function和Object的关系

在JavaScript 中Object和Function 有什么关系?前面说过JavaScript的终点都是一个Object。但是似乎理解有不理解,就是像是说linux中的所有程序都是文件一样。现在不先阐述这个理论,毕竟阐述理论说实话不是我擅长的,我擅长的就是举例子,然后根据例子来聊。

首先来神奇的猜结果:

console.log(Function instanceof Function);
console.log(Function instanceof Object);

console.log(Object instanceof Object);
console.log(Object instanceof Function);
 

大家猜一下结果?

在这里插入图片描述

透视true惊不惊喜意不意外。

首先来了解一下instanceof的是如何判断的。

instanceof

其实这个在前面聊三种判断数据类型,以及symbol类型的时候都说过。

看一下官网解释:

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

老规矩还是先用代码演示:

function  Test(){};
var test=new Test();
test instanceof Test

在这里插入图片描述

这个原理是什么,其实前面聊过原型以及原型链,可以翻看我前面的文章:浅谈原型和原型链

现在看一下test和Test所谓的原型以及原型链。

在这里插入图片描述

从这个地方可以看出两者的广联,这个就有一个神奇操作了,其实在Symbol中的一个属性也演示过,现在再来一个演示:

function  Test(){};
var test=new Test();
// 比如这样我们将其构造方法的原型修改了
Test.prototype={};
// 然后再这样操作一下
test instanceof Test

在这里插入图片描述

其实官网也这样说了:

需要注意的是,如果表达式 obj instanceof Foo 返回 true,则并不意味着该表达式会永远返回 true,因为 Foo.prototype 属性的值有可能会改变,改变之后的值很有可能不存在于 obj 的原型链上,这时原表达式的值就会成为 false。另外一种情况下,原表达式的值也会改变,就是改变对象 obj 的原型链的情况,虽然在目前的ES规范中,我们只能读取对象的原型而不能改变它,但借助于非标准的 __proto__ 伪属性,是可以实现的。比如执行 obj.__proto__ = {} 之后,obj instanceof Foo 就会返回 false 了。

当然如下操作也会返回错误:

function  Test(){};
var test=new Test();
test.__proto__={};
// 然后再这样操作一下
test instanceof Test

在这里插入图片描述

所以说用instanceof具体逻辑用白话说: instanceof 返回结果从new 的对象上的原型链(__proto__)上是否有构造方法的原型(prototype)

所以如下:

function  Test(){};
var test=new Test();
test instanceof Object

在这里插入图片描述

再如下看:

在这里插入图片描述

官网又这样说:

在浏览器中,我们的脚本可能需要在多个窗口之间进行交互。多个窗口意味着多个全局环境,不同的全局环境拥有不同的全局对象,从而拥有不同的内置类型构造函数。这可能会引发一些问题。比如,表达式 [] instanceof window.frames[0].Array 会返回 false,因为 Array.prototype !== window.frames[0].Array.prototype,并且数组从前者继承。

这个不再本篇讨论范围,简单的理解就是不同的window中的数组对象也是不同的。所以无法通过instanceof 进行判断。

现在知道了instanceof是如何实现的,现在看一下Function是什么?

Function

每个 JavaScript 函数实际上都是一个 Function 对象。运行 (function(){}).constructor === Function // true 便可以得到这个结论。

还是老规矩老代码演示:

function  Test(){};
var test=new Test();
test.constructor===Test

在这里插入图片描述

然后再来一个:

//test  是一new 出来的对象 ,所以需要用 Test
Test.constructor===Function

在这里插入图片描述

可以看出方法就是一个Function的对象。这样看是不是觉得稍微可以理解一些,当然这个也是由果推因。

还是老规矩,既然扯到官网,所以在补充官网的一个说明:

Function 构造函数与函数声明之间的不同:由 Function 构造函数创建的函数不会创建当前环境的闭包,它们总是被创建于全局环境,因此在运行时它们只能访问全局变量和自己的局部变量,不能访问它们被 Function 构造函数创建时所在的作用域的变量。这一点与使用 eval() 执行创建函数的代码不同。如果想要了解闭包可以看我的另一个文章:浅谈AO,GO,闭包

来一个例子演示:

var x = 10;

function createFunction1() {
    var x = 20;
    return new Function('return x;'); // 这里的 x 指向最上面全局作用域内的 x
}

function createFunction2() {
    var x = 20;
    function f() {
        return x; // 这里的 x 指向上方本地作用域内的 x
    }
    return f;
}

var f1 = createFunction1();
console.log(f1());          // 10
var f2 = createFunction2();
console.log(f2());          // 20

Object

Object 是 JavaScript 的一种 数据类型 。它用于存储各种键值集合和更复杂的实体。Objects 可以通过 Object() 构造函数或者使用 对象字面量 的方式创建。

简单的说:Object 构造函数创建一个对象包装器。Object构造函数为给定值创建一个对象包装器。如果给定值是 null 或 undefined,将会创建并返回一个空对象,否则,将返回一个与给定值对应类型的对象。 当以非构造函数形式被调用时,Object 等同于 new Object()。

简单的了解一些对象类型,可以看一下我的前面文章对象以及构造函数,当然这一篇文章只是简单说了一些对象类型。但是这个还有一个对象的创建方式不同方式,这个到时候再聊。

找一下Object 和Fuction的关系

前面说了instanceof的判断数据的关系,就是找对象的__proto__和构造方法prototype的关系。首先说一下:构造函数都有prototype

//Function的原型对象
 console.log(Function.prototype);
//Object的原型对象
console.log(Object.prototype);
//因为构造函数的prototype是一个对象 所以再搞一下是否能来一个原型链
console.log(Object.prototype.__proto__);
console.log(Function.prototype.__proto__);

现在看一下具体呈现了什么?

在这里插入图片描述

似乎也没有什么关系啊,现在继续执行看:

在这里插入图片描述

这样一看就发现这个神奇的地方,那就是Object.prototypeFunction.prototype.__proto__发现这两个竟然是一样的。

然后看一下是否真的相等:

console.log(Function.prototype.__proto__===Object.prototype);

在这里插入图片描述

然后再来一个神奇的测试,毕竟找到和对象的关系了,现在当作一对象试试:

Function.__proto__.__proto__

在这里插入图片描述

在这里插入图片描述

因此这个地方也就明白了:

console.log(Function instanceof Object);

在这里插入图片描述

这个也算也符号了对象的__proto__和构造函数的prototype。

现在又要反过来看是否可行?

既然这样根据前面了解原型和原型链的可以知道:对象都会从它的原型上继承一个 constructor 属性.

function  Test(){};
var test=new Test();

// 然后看一下
console.log(test.constructor);

在这里插入图片描述

在这里插入图片描述

既然冲上面看出Object和Function的尽头都是对象,那么一下其构造函数:

console.log(Object.constructor);

console.log(Function.constructor);

在这里插入图片描述

是不是发现一件神奇的事情,那就是两者的有一个关系,那么现在可以看一下是否两者相同:

console.log(Object.constructor === Function.constructor);

在这里插入图片描述

这个地方可以看出一件时间,那就是Object和Function的具有相同的构造函数。

根据前面test和Test的对比然后尝试一下:

Object.__proto__ === Function.prototype;   //true

所以可以得到如下:

Function.prototype.__proto__ === Object.prototype;//true
// 前面证明Function可以当作对象也可以如下
Function.__proto__.__proto__ === Object.prototype;//true

Object.__proto__ === Function.prototype;   //true

也就是复合了intanceof要求就是对象原型链和构造方法原型有相同的地方。

所以也就有了如下图(盗的图):

在这里插入图片描述

这个也就明白了为什么:

console.log(Function instanceof Function); //true
console.log(Function instanceof Object);//true

console.log(Object instanceof Object);//true
console.log(Object instanceof Function);//true
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值