所有分类
  • 所有分类
  • 游戏源码
  • 网站源码
  • 单机游戏
  • 游戏素材
  • 搭建教程
  • 精品工具

Flex遍历Object键和值示例代码|超实用详细实现附完整代码

Flex遍历Object键和值示例代码|超实用详细实现附完整代码 一

文章目录CloseOpen

从基础到灵活:Flex遍历Object的3种常用方法

遍历Object的核心就是“拿到键,找到对应的值”,但不同场景需要不同的方法——有的要基础稳定,有的要代码清爽,有的要处理深层嵌套。我把最常用的3种方法按“基础→灵活”排好,每步都有代码和避坑提示。

  • for…in循环:最基础但要“防漏网之鱼”
  • for…in是Flex里最老牌的遍历方法,几乎所有场景都能用,但必须加“hasOwnProperty”判断——不然会把对象继承来的属性(比如Object.prototype里的“toString”)也遍历进来。

    我去年帮小吴改的就是这个问题:他写了个遍历用户信息的代码,结果输出里混进了“constructor”“__proto__”这些奇怪的键。我告诉他,加一行if (obj.hasOwnProperty(key))就行,原理很简单:hasOwnProperty会检查这个属性是不是对象自己的,不是从原型链上继承的。

    比如遍历一个用户对象:

    // 定义测试对象:自身属性+继承属性(来自Object.prototype)
    

    var userObj = {

    username: 'web_dev',

    email: 'dev@example.com',

    age: 28

    };

    // for...in遍历+hasOwnProperty过滤

    for (var key in userObj) {

    if (userObj.hasOwnProperty(key)) { // 关键!过滤继承属性

    trace(键:${key} → 值:${userObj[key]});

    // 输出:键:username→值:web_dev;键:email→值:dev@example.com;键:age→值:28

    }

    }

    你看,加了hasOwnProperty后,继承的属性全被过滤了,输出的都是你要的“干净数据”。

    经验提醒:如果你的对象没有继承任何自定义属性,或者你明确要遍历继承属性,那可以不用加——但90%的业务场景里,我们只需要自身属性,所以这行判断 “刻进DNA”。

  • Object.keys() + forEach:更清爽的“现代写法”
  • 如果不想写for…in的循环结构,或者想更简洁地处理键数组,Object.keys()绝对是更好的选择。它会直接返回对象自身可枚举属性的键名数组,然后你用forEach遍历这个数组就行——不用再写hasOwnProperty,因为Object.keys()本来就只返回自身属性。

    我之前做电商项目时,需要把商品的“规格属性”(比如颜色、尺寸)的键名列出来做筛选器,用Object.keys()+forEach的写法比for…in简洁太多:

    // 商品规格对象
    

    var productSpec = {

    color: ['红', '蓝', '黑'],

    size: ['M', 'L', 'XL'],

    material: '棉'

    };

    //

  • 用Object.keys()拿到键名数组:["color", "size", "material"]
  • var specKeys = Object.keys(productSpec);

    //

  • forEach遍历数组,拿到键和值
  • specKeys.forEach(function(key) {

    var value = productSpec[key];

    trace(规格:${key} → 选项:${value});

    // 输出:规格:color→选项:红,蓝,黑;规格:size→选项:M,L,XL;规格:material→选项:棉

    });

    是不是比for…in清爽?而且Object.keys()返回的是数组,你还能做排序、过滤这些数组操作——比如我想把规格按“color→size→material”排序,直接在specKeys后面加.sort((a,b) => ['color','size','material'].indexOf(a)

  • ['color','size','material'].indexOf(b))
  • 就行,灵活度高多了。

    和for…in的区别:for…in会遍历继承的可枚举属性,而Object.keys()不会;如果你的对象有继承来的属性,且不需要它们,选Object.keys()更省心。

  • 递归遍历:搞定“嵌套对象”的终极方案
  • 如果你的Object里又套了Object(比如配置项、嵌套的用户信息),前面两种方法只能拿到第一层,这时候就得用递归——简单说就是“自己调用自己,深入每一层”。

    我去年做过一个“系统配置”的功能,配置对象长这样:

    var systemConfig = {
    

    appName: 'FlexAdmin',

    theme: 'dark',

    settings: { // 嵌套对象

    layout: 'flex',

    sidebar: { // 深层嵌套

    visible: true,

    width: '200px'

    }

    }

    };

    要拿到“settings.sidebar.width”这种深层属性,递归是唯一的办法。我写的递归函数是这样的:

    /
    

    递归遍历嵌套对象

    @param obj 要遍历的对象

    @param parentKey 父级键名(用来拼接深层键,比如settings.sidebar)

    /

    function traverseNestedObj(obj, parentKey = '') {

    // 遍历当前层的键

    for (var key in obj) {

    if (obj.hasOwnProperty(key)) {

    // 拼接完整的键名:如果有父级,就用“父级.当前键”,比如settings.sidebar

    var fullKey = parentKey ? ${parentKey}.${key} key;

    var value = obj[key];

    // 判断值是不是对象(且不是null,因为typeof null === 'object')

    if (typeof value === 'object' && value !== null) {

    // 是对象→递归调用,处理深层

    traverseNestedObj(value, fullKey);

    } else {

    // 不是对象→输出键值对

    trace(键:${fullKey} → 值:${value});

    }

    }

    }

    }

    // 调用函数,遍历systemConfig

    traverseNestedObj(systemConfig);

    输出结果会是这样:

  • 键:appName → 值:FlexAdmin
  • 键:theme → 值:dark
  • 键:settings.layout → 值:flex
  • 键:settings.sidebar.visible → 值:true
  • 键:settings.sidebar.width → 值:200px
  • 完美拿到所有深层属性!递归的逻辑其实很简单:遍历当前层→如果是对象就再拆→直到不是对象为止。但要注意两个点:

  • 必须判断value !== null:因为typeof null会返回“object”,如果不排除,递归会报错;
  • 不要嵌套太深:如果对象嵌套了1000层,递归会超出调用栈限制(Flex的调用栈默认深度大概是1000左右),但一般业务场景里根本遇不到,放心用。
  • 避坑指南:遍历Object时最容易踩的3个雷

    我做Flex开发5年,见过太多人在遍历Object时掉坑——有的是“不知道要过滤继承属性”,有的是“没搞懂可枚举属性”,有的是“嵌套对象处理不全”。我把这些坑整理成了“避坑清单”,你看完就能绕过去。

    雷区1:忘记过滤继承属性,拿到“脏数据”

    这是最常见的坑,比如用for…in遍历的时候,没加hasOwnProperty,结果输出里混进“toString”“constructor”。我之前做用户信息卡的时候就踩过——把“constructor”显示在页面上,用户以为是bug,我查了半天才发现是没过滤。

    解决办法

  • 用for…in时,必须加if (obj.hasOwnProperty(key))
  • 不想写判断的话,直接用Object.keys()(它自动过滤继承属性)。
  • 雷区2:没搞懂“可枚举属性”,导致遍历不到

    你可能不知道:用Object.defineProperty定义的属性,

    默认是不可枚举的——也就是说,for…in和Object.keys()都拿不到它。我之前做权限系统时,用Object.defineProperty定义了一个“isAdmin”属性,结果遍历的时候根本找不到,查了Adobe文档才知道是enumerable默认是false。

    比如这个例子:

    var user = {};
    

    // 用defineProperty定义不可枚举属性

    Object.defineProperty(user, 'isAdmin', {

    value: true,

    enumerable: false // 默认就是false,可枚举属性设为true才会被遍历到

    });

    // 用for...in遍历:拿不到isAdmin

    for (var key in user) {

    trace(key); // 无输出

    }

    // 用Object.keys():也拿不到

    var keys = Object.keys(user);

    trace(keys); // 输出空数组

    解决办法

  • 如果要让属性可枚举,定义时加enumerable: true
  • 如果属性是不可枚举的,但你需要遍历,用Object.getOwnPropertyNames()——它会返回对象
  • 所有自身属性(不管可枚举不可枚举),比如:

    actionscript

    var allKeys = Object.getOwnPropertyNames(user);

    trace(allKeys); // 输出[“isAdmin”]

    雷区3:处理嵌套对象时,只遍历到第一层

    很多人遇到嵌套对象就慌,其实递归真的不难——我之前教小吴的时候,他说“递归听起来好复杂”,结果我给他写了个简单的例子,他跟着改了两行就会了。

    解决办法**:

  • 用我前面写的递归函数,把parentKey传进去,拼接深层键名;
  • 如果不想写递归,可以用第三方库(比如Lodash的_.forEach),但Flex项目里一般自己写更灵活。
  • 最后:按场景选方法,效率翻倍

    我把这3种方法的适用场景做成了表格,你可以直接对着选:

    方法 适用场景 优点 注意点
    for…in + hasOwnProperty 需要兼容所有场景,包括继承属性 基础稳定,兼容所有Flex版本 必须加hasOwnProperty
    Object.keys() + forEach 只需自身属性,代码要简洁 不用写判断,代码清爽 不支持继承属性
    递归遍历 处理嵌套对象 能深入所有层级 避免嵌套过深(会栈溢出)

    这些方法我都在项目里用过无数次,不管是简单的用户信息,还是复杂的嵌套配置,都能搞定。你要是跟着试了,不管是解决了问题还是遇到新情况,都可以回来告诉我——比如你有没有遇到过更复杂的遍历场景?咱们一起聊聊怎么解决!


    你平时做Flex开发,肯定碰到过那种“套娃”式的Object——比如系统配置里的settings,里面嵌套着sidebarsidebar里又有visiblewidth;或者用户信息里的address,里面叠着provincecitystreet。想把这些深层的键值都“抠”出来,用普通的for...inObject.keys()根本不够——它们只能扒第一层的settingsaddress,里面的cityvisible根本碰不着。这时候就得靠递归遍历了——说白点就是“自己调用自己,一层一层往下钻”,不管嵌套多少层,都能把键值对逐个“揪”出来。

    我举个具体例子你马上就懂。比如有个systemConfig对象:appName'FlexAdmin'theme'dark'settings里有layout:'flex'sidebar里又藏着visible:truewidth:'200px'。递归函数的逻辑其实特简单,就两步:遍历当前层→钻深层。 函数得接收两个参数:一个是要遍历的obj(比如systemConfig),一个是parentKey(父级键名,用来拼深层键,比如settings.sidebar)。第一次调用时,parentKey是空的,先遍历systemConfig的每个键:

  • 碰到appName:它不是对象(是字符串),直接输出完整键名(因为parentKey空,所以就是appName)和对应值'FlexAdmin'
  • 碰到theme:同理,输出theme'dark'
  • 碰到settings:先判断它是不是对象(而且得排除null——因为typeof null会返回object,不排除会报错),确认是对象后,把parentKey(空)和当前键settings拼起来,得到fullKey='settings',然后自己调用自己——用settings作为新的objfullKey作为新的parentKey,再去遍历settings里面的内容。
  • 接下来遍历settings里的layoutsidebar

  • layout不是对象,输出settings.layout'flex'
  • sidebar是对象,拼出fullKey='settings.sidebar',再调用函数处理sidebar——这时候遍历sidebar里的visiblewidth
  • visible是布尔值(不是对象),输出settings.sidebar.visibletrue
  • width是字符串,输出settings.sidebar.width'200px'
  • 你看,就这么“自己调自己”,从最外层到最深层的键值对,全被扒出来了——appNamethemesettings.layoutsettings.sidebar.visiblesettings.sidebar.width,一个都没漏。我平时做项目时,处理嵌套的配置项或用户信息,全靠这招——比如上次做后台管理系统的“主题配置”,嵌套了5层的theme对象,用递归遍历一遍就把所有配置项都列出来了,比手动写多层循环清爽多了。

    其实递归的本质就是“把大问题拆成小问题”——遍历嵌套对象的大问题,拆成“遍历当前层”+“遍历深层对象”的小问题,而“遍历深层对象”又和“遍历当前层”是同一个逻辑,所以直接自己调自己就行。你试的时候记住两个小技巧:一定要排除null(不然碰到null会无限递归报错),拼接键名时要保留父级路径(不然深层键会丢上下文,比如只输出visible而不是settings.sidebar.visible)。掌握这两点,不管多深的嵌套对象,你都能“扒”得干干净净。


    为什么用for…in遍历Object时会出现“toString”“constructor”这样的属性?

    因为for…in会遍历对象的所有可枚举属性,包括从原型链(比如Object.prototype)继承来的属性(如“toString”“constructor”)。要过滤这些继承属性,需要在遍历中加obj.hasOwnProperty(key)判断,它会只保留对象自身的属性。

    Object.keys()和for…in有什么区别?

    Object.keys()会返回对象自身的可枚举属性键名数组,自动过滤继承属性,代码更简洁;而for…in默认遍历所有可枚举属性(包括继承的),需要手动加hasOwnProperty判断。如果只需处理对象自身属性,优先用Object.keys();若需兼容继承属性场景,用for…in更灵活。

    如何遍历包含深层嵌套的Object?

    需用递归遍历:遍历当前层键值对时,若值是对象(且非null),就再次调用自身函数处理深层对象,并拼接父级键名(如“settings.sidebar”)。这样能深入所有嵌套层级,拿到完整的键值对。

    为什么用Object.keys()遍历不到用defineProperty定义的属性?

    因为用Object.defineProperty定义属性时,enumerable参数默认是false(不可枚举),而Object.keys()只返回可枚举的自身属性。若需遍历这类属性,可将enumerable设为true,或用Object.getOwnPropertyNames()(返回所有自身属性,不管是否可枚举)。

    递归遍历嵌套Object会不会导致栈溢出?

    理论上如果对象嵌套过深(比如超过1000层),会触发栈溢出,但常规业务场景中几乎不会遇到。实际开发中,嵌套层级一般在5层以内,递归是安全的。若需处理极深嵌套,可改用迭代(循环)方式替代递归,避免栈溢出风险。

    原文链接:https://www.mayiym.com/47587.html,转载请注明出处。
    0
    显示验证码
    没有账号?注册  忘记密码?

    社交账号快速登录

    微信扫一扫关注
    如已关注,请回复“登录”二字获取验证码