吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 951|回复: 27
收起左侧

[求助] 请教大佬一个JS问题

  [复制链接]
waahah 发表于 2023-6-15 23:26

请教大佬一个问题,可以从底层的层面解释一下为什么 console.info(dict.node) 输出的是 undefined 的原因吗



<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        window.onload = () => { 
                const dict = {
                    conform : document.querySelector("#admin"),
                    dimmer : document.querySelector('#pwd')
                }
                for(const node of Object.keys(dict)){
                    console.info(dict.node);
                }
            }
    </script>
</head>

<body>
    <form id="form1" name="form1" method="post" action="">
        <table width="200" border="0" align="center">
            <tr>
                <td colspan="2"></td>
            </tr>
            <tr>
                <td width="62">帐号:</td>
                <td width="122">
                    <input name="admin" type="text" id="admin" size="15" />
                </td>
            </tr>
            <tr>
                <td>密码:</td>
                <td><input name="pwd" type="password" id="pwd" size="15" /></td>
            </tr>
        </table>
    </form>
</body>

</html>

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
为之奈何? + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

hans7 发表于 2023-6-16 00:08
本帖最后由 hans7 于 2023-6-16 00:55 编辑

想实现这个例子的目标只需要把dict.node改成dict[node],dict.node相当于dict['node']。

打开 https://astexplorer.net/ 查看 这条语句 dict.node === dict[node] 的Babel AST

捕获.JPG

两者区别只有一个:computed是true和false。但含义是不一样的。

接下来看下computed是true和false时v8生成的字节码的区别。准备一段代码 computed_demo.js

let dict = {
    node: 'node'
};
let node = '_node';
console.log(dict.node === dict[node]);


命令:./d8 computed_demo.js --print-bytecode

获取字节码。如果没有d8.exe也可以用nodejs代替,node --print-bytecode computed_demo.js。简单分析如下。结论很简单:dict.node用了LdaNamedProperty指令,dict[node]用了LdaKeyedProperty指令。这就是两者的不同。Lda类指令是将结果放到累加寄存器的。

[generated bytecode for function:  (0x00650824fa59 <SharedFunctionInfo>)]
Parameter count 1
Register count 5
Frame size 40
         000000650824FADA @    0 : 7d 00 00 29       CreateObjectLiteral [0], [0], #41 ; 定义 dict
         000000650824FADE @    4 : 1d 02             StaCurrentContextSlot [2] ; 简单理解为放到 globalThis 地址2处
         000000650824FAE0 @    6 : 12 01             LdaConstant [1] ; 常量池[1]处为字符串 '_node'
         000000650824FAE2 @    8 : 1d 03             StaCurrentContextSlot [3]
         000000650824FAE4 @   10 : 13 02 01          LdaGlobal [2], [1] ; 取常量池2处的值,即'console',放到累加寄存器。后面的 [1] 是反馈向量,本例不用管。
         000000650824FAE7 @   13 : 26 f9             Star r2 ; 累加寄存器当前值存入r2寄存器,即r2 = 'console'
         000000650824FAE9 @   15 : 28 f9 03 03       LdaNamedProperty r2, [3], [3] ; console取log属性
         000000650824FAED @   19 : 26 fa             Star r1 ; console.log对象的地址放到r1寄存器
         000000650824FAEF @   21 : 1a 02             LdaCurrentContextSlot [2] ; globalThis [2]对应dict,加载到累加寄存器
         000000650824FAF1 @   23 : 26 f8             Star r3 ; r3现在指向dict对象
         000000650824FAF3 @   25 : 28 f8 04 05       LdaNamedProperty r3, [4], [5] ; 常量池[4]对应'node',dict取'node'属性
         000000650824FAF7 @   29 : 26 f8             Star r3 ; dict['node']结果放到r3寄存器
         000000650824FAF9 @   31 : 1a 02             LdaCurrentContextSlot [2]
         000000650824FAFB @   33 : 26 f7             Star r4 ; r4指向dict对象
         000000650824FAFD @   35 : 1a 03             LdaCurrentContextSlot [3] ; globalThis [3]对应'_node',至累加寄存器
         000000650824FAFF @   37 : 2a f7 07          LdaKeyedProperty r4, [7] ; 取dict[node],即dict['_node'],结果放在累加寄存器
         000000650824FB02 @   40 : 68 f8 09          TestEqualStrict r3, [9] ; 累加寄存器当前值与r3的值比较,结果放到累加寄存器
         000000650824FB05 @   43 : 26 f8             Star r3 ; dict.node === dict[node]结果放到r3
         000000650824FB07 @   45 : 59 fa f9 f8 0a    CallProperty1 r1, r2, r3, [10] ; 调用console.log
         000000650824FB0C @   50 : 26 fb             Star r0
         000000650824FB0E @   52 : aa                Return 
Constant pool (size = 5)
000000650824FA9D: [FixedArray] in OldSpace
 - map: 0x0065080404b1 <Map>
 - length: 5
           0: 0x00650824fa81 <ObjectBoilerplateDescription[3]>
           1: 0x00650824fa11 <String[#5]: _node>
           2: 0x0065081c6971 <String[#7]: console>
           3: 0x0065081c69e5 <String[#3]: log>
           4: 0x00650824fa01 <String[#4]: node>
Handler Table (size = 0)
Source Position Table (size = 0)
false

感觉这些内容足够水一篇blog了

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
空心 + 1 + 1 我很赞同!

查看全部评分

metaxman 发表于 2023-6-16 00:04
在javascript中,对象取值基本的有两种方式,一种是使用"."的方式,这种你应该清楚,这种方式语言执行时,一般是已知属性名取值,当取不到就会返回undefined。另一种是通过 obj['paramName'],中括号中可以是string或者变量的方式去取值,字符串则和之前点取值的方式一样,使用变量即可以做到动态取值设置值。你这段代码用在循环中,肯定是变量属性名,所以要使用[]的方式来取值遍历读取。
metaxman 发表于 2023-6-16 00:09
metaxman 发表于 2023-6-16 00:04
在javascript中,对象取值基本的有两种方式,一种是使用"."的方式,这种你应该清楚,这种方式语言执行时, ...

大白话就是你想去找循环遍历的 node 变量属性名,但用错了方式,它觉得你找对象中的“node”属性,一看对象里没有呀,哦,抱歉同志,只能say undefined了。
 楼主| waahah 发表于 2023-6-16 00:21
metaxman 发表于 2023-6-16 00:04
在javascript中,对象取值基本的有两种方式,一种是使用"."的方式,这种你应该清楚,这种方式语言执行时, ...

感谢回复,那怎么分辨什么时候用 . 又什么时候用[],交叉用呢。还有在我看来 . 和 [] 不是一样的吗
metaxman 发表于 2023-6-16 00:29
waahah 发表于 2023-6-16 00:21
感谢回复,那怎么分辨什么时候用 . 又什么时候用[],交叉用呢。还有在我看来 . 和 [] 不是一样的吗

当属性名是一个变量时必须得用[],就像4楼说的,dict.node相当于dict['node']。你理解这个,就可以了。不想区分就全用[],但使用点属性名的方式编写更便捷。
metaxman 发表于 2023-6-16 00:32
waahah 发表于 2023-6-16 00:21
感谢回复,那怎么分辨什么时候用 . 又什么时候用[],交叉用呢。还有在我看来 . 和 [] 不是一样的吗

dict[node] 和 dict['node'] 写法上很明显不一样吧,dict.node相当于 dict['node'],所以 dict.node 怎么能和 dict[node] 一样呢。
69之皇 发表于 2023-6-16 00:45
dict[node] 这个node可以是任何key,而dict["node"]表示这个key只能是node
 楼主| waahah 发表于 2023-6-16 00:48
69之皇 发表于 2023-6-16 00:45
dict[node] 这个node可以是任何key,而dict["node"]表示这个key只能是node

这个我知道,在这个循环里 dict[noed]就相当于不循环直接调用的dict["node"]
 楼主| waahah 发表于 2023-6-16 00:58
metaxman 发表于 2023-6-16 00:29
当属性名是一个变量时必须得用[],就像4楼说的,dict.node相当于dict['node']。你理解这个,就可以了。不 ...
                const dict = {
                    conform : document.querySelector("#admin"),
                    dimmer : document.querySelector('#pwd')
                }

                dict["conform"]
                //正确

                dict.conform == dict["conform"]
                //结果为true
我知道dict.node相当于dict["node"],所以在循环块我才写成dict.node,因为平常不在循环块里时都是直接用dict.node (它俩用哪个都行相等),就是在循环块里我也是潜意识里也还认为它俩相等,就是不知道为啥到了循环块里就不一样了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 21:37

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表