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”索引位于请求对象的原型中