最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • JS之日常解题

    正文概述 掘金(星空海绵)   2021-01-01   568

    1.取出对象中一部分放到另一个对象中

    今天下午在掘金摸鱼的时候,看见有一个小同学发了一个沸点

    JS之日常解题

    嗯嗯 ,日常要我写的话,以前可能我也会这么写,但是经过我最近一段时间的学习,我可能会用解构赋值来写

            const objOne = {
                name: 'xiaoMing',
                age: 18,
                id: 1234,
                gender: 1
            }
            const { name, id } = objOne;
            const objTwo = { name, id };
    

    我可能会像上面这样写,这些些真的很优雅吗,我觉得跟上面那位小同学写的也没什么区别,还多一行代码,并不是一个好的方案,像我这么机灵的搜索引擎工程师,那么我就开始Google一下,于是找到一个讨论贴,针不戳,里面果然有几种比较秒的写法,显得有点高端。

    (1)第一种

            const objOne = {
                name: 'xiaoMing',
                age: 18,
                id: 1234,
                gender: 1
            }
            const { age, gender, ...objTwo } = objOne;
    

    这种也是利用的对象解构,把剩余的值赋给了objTwo,但是如果我原对象中有30个属性,我只需要取两个呢,那我岂不是得写很多。

    (2)第二种

            const objOne = {
                name: 'xiaoMing',
                age: 18,
                id: 1234,
                gender: 1
            }
            const objTwo = (({ name, id }) => ({ name, id }))(objOne)
    

    上面这种也是解构,不过这里用了一个立即执行函数,还是比较秒的,但是本质上还是解构的思想,跟上面的有同样的问题,假如我要取28个属性呢,那岂不是要写很多。

    (3)第三种

            const objOne = {
                name: 'xiaoMing',
                age: 18,
                id: 1234,
                gender: 1
            }
            const pick = (obj, arr) => arr.reduce((iter, val) =>
                (val in obj && (iter[val] = obj[val]), iter), {});
    
            const objTwo = pick(objOne, ['name', 'id']);
    

    这种刚看是不是还有点不明白,首先箭头函数箭头后面不写大括号{}的时候,会自动return,这是箭头函数带的特性,再就是 (val in obj && (iter[val] = obj[val]), iter) 这一句代码是不是看着有点不是很懂,前面倒是知道,就是判断,那这个逗号是什么意思呢,其实我刚看也没看懂,就直接翻了一下 逗号操作符--MDN

    也就是说上面这一行代码会返回每次的操作结果,然后用这个操作结果再进行下一次操作,上面的代码也就相当于:

            const objOne = {
                name: 'xiaoMing',
                age: 18,
                id: 1234,
                gender: 1
            }
            const pick = (obj, arr) => arr.reduce((iter, val) => {
                if (val in obj && (iter[val] = obj[val])) {
                    return iter
                }
            }, {});
            const objTwo = pick(objOne, ['name', 'id']);
    

    但是上面用逗号写的确实会更简洁,对不懂逗号操作符的人来说可能不是很明了。

    2.判断一个变量同时等于多个数值

    这是今天看B站上的一个UP的视频里面,UP提出来的,当然之前我也看到过,只是没有仔细的研究,只是今天看视频又看见了,想着连着上面那一题一起记录一下吧,毕竟好记性不如烂笔头嘛??

            if (a == 1 && a == 2 && a == 3) {
                console.log('星空海绵');
            }
    

    上面写一段是什么代码可以让这个判断成立,执行打印的代码,首先一看到这个题目,大家应该想到,想要这个判断成立,a肯定得是一个变化得值,每使用一次就加1,那么这个判断才有可能成立,好了,怎样让这个判断成立的思路已经有了,现在的问题就是怎么让a每使用一次就加1呢。 首先我们来看一下 == 操作符成立的条件:

    • 1.如果两个操作数都是对象,则仅当两个操作数都引用同一个对象时才返回true。
    • 2.如果一个操作数是null,另一个操作数是undefined,则返回true。
    • 3.如果两个操作数是不同类型的,就会尝试在比较之前将它们转换为相同类型:
      • 1.当数字与字符串进行比较时,会尝试将字符串转换为数字值。
      • 2.如果操作数之一是Boolean,则将布尔操作数转换为1或0。true转成1,false转成0。
      • 3.如果操作数之一是对象,另一个是数字或字符串,会尝试使用对象的valueOf()和toString()方法将对象转换为原始值。
    • 4.如果操作数具有相同的类型,则将它们进行如下比较:
      • 1.String:true仅当两个操作数具有相同顺序的相同字符时才返回。
      • 2.Number:true仅当两个操作数具有相同的值时才返回。+0并被-0视为相同的值。如果任一操作数为NaN,则返回false。
      • 3.Boolean:true仅当操作数为两个true或两个false时才返回true。

    (1)第一种解法

    看到上面 == 运算符的相关成立条件后,我们再来分析上面这一题,当 a 是 number 类型时,只有每次访问后都加1上面的判断才会成立。那么我们看下上面的代码,这个a没用var或者let及const定义,那就是隐式变量,当然我们也可在上面定义a,就单纯这个式子而言,a是隐式变量,隐式变量再浏览器中是挂在全局对象window下面的,也就是说a是window对象下的一个属性,然后对象有一个 Object.defineProperty() 方法,这个方法能定义和修改一个对象上的属性,并且返回此对象。

            let _default = 0
            Object.defineProperty(window, 'a', {
                get() {
                    return ++_default;
                }
            })
            if (a == 1 && a == 2 && a == 3) {
                console.log('星空海绵');
            }
    

    此时通过上面这段代码我们发现这个判断成立,此时如果我们把 == 改成 === 成立吗,照样是成立的,因为此时a每次增加1并保持自己的类型为number,也就是说上面这段代码不仅适用于 == ,同时也适用于 === 。

    (2)第二种解法

    看到上面 == 运算符的介绍,我们发现 如果操作数之一是对象,另一个是数字或字符串,会尝试使用对象的valueOf()和toString()方法将对象转换为原始值。 有这么一个规则,也就是说假如现在上面的a是对象的话,会尝试使用valueOf方法和toSting方法,那么我们去修改这两个方法中的其中一个行吗

            let a = {
                _default: 0,
                valueOf: function () {
                    return ++this._default;
                }
            }
            if (a == 1 && a == 2 && a == 3) {
                console.log('星空海绵');
            }
    
            let a = {
                _default: 0,
                toString: function () {
                    return ++this._default;
                }
            }
            if (a == 1 && a == 2 && a == 3) {
                console.log('星空海绵');
            }
    

    以上两种方法都可以,一个是重写a对象的valueOf方法,一个是重写对象的toString()方法。

    3.深入类型转换

    首先上题目

            console.log(({} + {}).length);
            console.log(([] + []).length);
            console.log(([] + {}).length);
            console.log((function () { }).length);
    

    上面这4个console分别打印什么,首先第一个其实是两个空对象相加,那么空对象怎么相加呢,它们会自动转成字符串相加,也就是调用toString方法,也就是说{}.toSting(),那么这个结果是什么呢,这个结果是 [object object],此时你是不是想到了判断类型的 Object.prototype.toString.call() ,既然知道原理了,那第一个console的答案就是 "[object object]"+"[object object]",也就是30, 第二个可能不用说大家都知道是0,因为[]空数组转换成数值类型是0,根据上面两题我们知道这个答案是 0+"[object object]",也就是15,那么最后一题呢,我们不妨打印 console.dir(function () { }); 看一下,发现这个里面带了一个length属性,那么这个length属性是什么呢,其实是参数列表的个数,相当于 arguments.length,所以最后一个的结果也是0。

            console.log(({} + {}).length); // 30
            console.log(([] + []).length); // 0
            console.log(([] + {}).length); // 15
            console.log((function () { }).length); // 0
    

    完!


    起源地下载网 » JS之日常解题

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元