Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/35.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么Express属性ip不出现在Object.keys(请求)中?_Javascript_Node.js_Http_Express - Fatal编程技术网

Javascript 为什么Express属性ip不出现在Object.keys(请求)中?

Javascript 为什么Express属性ip不出现在Object.keys(请求)中?,javascript,node.js,http,express,Javascript,Node.js,Http,Express,考虑以下代码: const express = require('express'); const app = express(); app.get('/', function(request, response) { console.log(Object.keys(request)); console.log(request.ip); }); app.listen(1337); 在第一个日志中,我们可以看到ip不是request的属性,但在第二个日志中,打印了ip。为什么会发

考虑以下代码:

const express = require('express');
const app = express();
app.get('/', function(request, response) {
    console.log(Object.keys(request));
    console.log(request.ip);
});
app.listen(1337);

在第一个日志中,我们可以看到
ip
不是
request
的属性,但在第二个日志中,打印了
ip
。为什么会发生这种情况?

根据Express的源代码

表示ip索引不在请求对象内,默认情况下,express将该索引作为函数返回信任代理fn的值,并通过传递proxyaddr返回该索引

Object.keys(Object) <- This only returns the indices that appear in the object.
Object.keys(Object)我想这是因为。它实际上是在创建一个新实例,并使用
req
模块作为原型

如果执行此操作,您将看到IP属性:

var express = require('express')
Object.keys(express.request)
您要返回的键是实例的键,而不是原型链中的所有属性。事实上,它嵌套了两层:

var p1 = Object.getPrototypeOf(req)
var p2 = Object.getPrototypeOf(p1)
console.log(Object.keys(p1)) // ['app']
console.log(Object.keys(p2)) // [..., 'ip', ...]
Object.keys()
返回给定对象自身可枚举属性的数组(可枚举只是意味着,如果您尝试遍历该对象,则仅循环那些可枚举属性设置为
true
的属性——请参见
Object.getOwnPropertyDescriptor

这可能意味着
ip
属性不属于
request
对象,并且
request
对象正在原型链的某个位置继承
ip
属性

要真正证明这一点,可以使用
Object.getPrototypeOf()
方法

首先,我只是尝试了
Object.getPrototypeOf(req)
,但在返回的对象上找不到
ip
属性。所以我进一步深入到原型链中

console.log(Object.getPrototypeOf(Object.getPrototypeOf(req))

这返回了一个属性为ip的对象

IncomingMessage {
  ...
  acceptsEncodings: [Function]
  ip: [Getter],
  ips: [Getter],
  ...
}
如前所述,由于
ip
address属性是从原型链继承的,
Object.keys()
没有将
ip
列为
req
对象的属性

它还突出显示了JS中另一个简洁的特性:Getters,也称为计算属性值

有时,允许访问返回数据的属性是可取的 动态计算的值,或者您可能希望反映 不需要使用显式方法的内部变量 电话。阅读有关MDN的信息


这正是这里发生的事情。Express有一些内部逻辑,用于从http请求的负载中选择IP地址,而不是让您像这样访问IP地址:
req.IP()
,Express开发者已选择将
ip
属性绑定到一个函数,当您访问
ip
属性时,该函数将被调用,您只需通过
req.ip

返回对象自身可枚举属性的数组即可访问ip地址。因此,如果
ip
属于原型链中的某个位置(未拥有)或标记为不可枚举属性,那么它将不会被列出。。。数组也会发生同样的情况:
Object.keys(someArray)
不包含
length
属性。它似乎被标记为
enumerable:true
并设置为自己的属性。关于原型和所有这些东西,我可以从哪里获得更多信息?Gustavo,在这个链接中,因为“ip”索引位于请求对象的原型中