最新公告
  • 欢迎您访问爱上源码网,分享精品整站源码,网站模板,游戏源码,APP小程序源码以及视频教程免费下载;服务永无止境!立即加入我们
  • JavaScript的技巧

    在 JavaScript 中 数组(Array)随处可见,使用ECMAScript 6 中的新特性 扩展运算符 我们可以做很多很棒事情。

    1. 迭代一个空数组

    JavaScript 中直接创建的数组是松散的,以至于会有很多坑。试着用数组的构造方法创建一个数组,你就会瞬间明白了。

    const arr = new Array(4);
    [undefined, undefined, undefined, undefined]
    // 谷歌浏览器中是 [empty x 4]

    你会发现,通过一个松散的数组去循环调用一些转换是非常难的。

    const arr = new Array(4);
    arr.map((elem, index) => index);
    [undefined, undefined, undefined, undefined]

    想要解决这个问题,你可以使用在创建新数组的时候使用 Array.apply。

    const arr = Array.apply(null, new Array(4));
    arr.map((elem, index) => index);
    [0, 1, 2, 3]

    2. 给方法传一个空参数

    如果你想调用一个方法,并不填其中的一个参数时,JavaScript 就会报错。

    method('parameter1', , 'parameter3'); // Uncaught SyntaxError: Unexpected token ,

    一个我们常用的解决方法是传递 null 或 undefined。

    method('parameter1', null, 'parameter3') // or
    method('parameter1', undefined, 'parameter3');

    根据 ES6 中对扩展运算符的介绍,有一个更简洁的方法可以将空参数传递给一个方法。正如上面所提到的,数组是松散的,所以给它传空值是可以的,我们正是用到了这个优点。

    method(...['parameter1', , 'parameter3']); // 代码执行了...

    3. 数组去重

    我一直不明白为什么数组不提供一个内置函数可以让我们方便的取到去重以后的值。扩展运算符帮到了我们,使用扩展运算符配合 Set可以生成一个不重复的数组。

    const arr = [...new Set([1, 2, 3, 3])];
    // [1, 2, 3]

    4.从后向前获取数组元素

    如果你想从后向前获取一个数组的元素,可以这样写:

    var arr = [1, 2, 3, 4]
    
    console.log(arr.slice(-1)) // [4]
    console.log(arr.slice(-2)) // [3, 4]
    console.log(arr.slice(-3)) // [2, 3, 4]
    console.log(arr.slice(-4)) // [1, 2, 3, 4]

    5.短路条件句

    如果你想在某个条件逻辑值为true时,执行某个函数,就像这样:

    if (condition) {
      dosomething()
    }

    这时,你可以这样子运用短路:

    condition && dosomething()

    6.用操作符 “||” 来设置默认值

    如果你必须给一个变量赋默认值,可以简单的这样写:

    var a
    
    console.log(a) // undefined
    a = a || 'default value'
    console.log(a) // default value
    a = a || 'new value'
    console.log(a) // default value

    7.在相等比较中使用 Object.is()

    我们都知道 JavasSript 是弱类型的,并且当我们使用==作比较时,在一些情况下由于类型转换或者说“把两个操作数中的一个转换成另一个,然后再比较”,会出现意想不到的结果。就像这样:

    0 == ' ' //true
    null == undefined //true
    [1] == true //true

    因此 JavaScript 中给我们提供了全等操作符 ===, 它比不全等操作符更加严格并且不会发生类型转换。但是用 === 来进行比较并不是最好的解决方案。你可能会得到:

    NaN === NaN //false

    ES6 中提供了新的 Object.is() 方法,它具有 === 的一些特点,而且更好、更精确,在一些特殊案例中表现的很好:

    Object.is(0 , ' '); //false
    Object.is(null, undefined); //false
    Object.is([1], true); //false
    Object.is(NaN, NaN); //true

    8.给一个函数 Bind 对象

    我们经常需要将一个对象绑定到一个方法的 this 上。在 JS 中,如果你想要调用一个函数并指定它的 this 时可以使用 bind 方法。

    Bind 语法

    fun.bind(thisArg[, arg1[, arg2[, ...]]])

    参数

    thisArg

    当绑定函数被调用时,该参数会作为原函数运行时的 this 指向。

    arg1, arg2, …

    当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。

    返回值

    返回由指定的this值和初始化参数改造的原函数拷贝

    JS 中的实例

    const myCar = {
     brand: 'Ford',
     type: 'Sedan',
     color: 'Red'
    };
    
    const getBrand = function () {
     console.log(this.brand);
    };
    
    const getType = function () {
     console.log(this.type);
    };
    
    const getColor = function () {
     console.log(this.color);
    };
    
    getBrand(); // object not bind,undefined
    
    getBrand(myCar); // object not bind,undefined
    
    getType.bind(myCar)(); // Sedan
    
    let boundGetColor = getColor.bind(myCar);
    boundGetColor(); // Red

    9.获取文件拓展名

    解决方法 1: 正则表达式

    function getFileExtension1(filename) {
      return (/[.]/.exec(filename)) ? /[^.]+$/.exec(filename)[0] : undefined;
    }

    解决方法 2: String的split方法

    function getFileExtension2(filename) {
      return filename.split('.').pop();
    }

    这两种解决方法不能解决一些边缘情况,这有另一个更加强大的解决方法。

    解决方法 3: String的slice、lastIndexOf方法

    function getFileExtension3(filename) {
      return filename.slice((filename.lastIndexOf(".") - 1 >>> 0) + 2);
    }
    
    console.log(getFileExtension3(''));                            // ''
    console.log(getFileExtension3('filename'));                    // ''
    console.log(getFileExtension3('filename.txt'));                // 'txt'
    console.log(getFileExtension3('.hiddenfile'));                 // ''
    console.log(getFileExtension3('filename.with.many.dots.ext')); // 'ext'

    这是如何实现的呢?

    • String.lastIndexOf() 方法返回指定值(本例中的’.’)在调用该方法的字符串中最后出现的位置,如果没找到则返回 -1。

    • 对于’filename’和’.hiddenfile’,lastIndexOf的返回值分别为0和-1无符号右移操作符(»>) 将-1转换为4294967295,将-2转换为4294967294,这个方法可以保证边缘情况时文件名不变。

    • String.prototype.slice() 从上面计算的索引处提取文件的扩展名。如果索引比文件名的长度大,结果为””。

    10.预防unapply攻击

    重写内置对象的原型方法,外部代码可以通过重写代码达到暴漏和修改已绑定参数的函数。这在es5的方法下使用polyfill时是一个严重的安全问题。

    // bind polyfill 示例
    function bind(fn) {
      var prev = Array.prototype.slice.call(arguments, 1);
      return function bound() {
        var curr = Array.prototype.slice.call(arguments, 0);
        var args = Array.prototype.concat.apply(prev, curr);
        return fn.apply(null, args);
      };
    }
    
    
    // unapply攻击
    function unapplyAttack() {
      var concat = Array.prototype.concat;
      Array.prototype.concat = function replaceAll() {
        Array.prototype.concat = concat; // restore the correct version
        var curr = Array.prototype.slice.call(arguments, 0);
        var result = concat.apply([], curr);
        return result;
      };
    }

    上面的函数声明忽略了函数bind的prev参数,意味着调用unapplyAttack之后首次调用.concat将会抛出错误。

    使用Object.freeze,可以使对象不可变,你可以防止任何内置对象原型方法被重写。

    (function freezePrototypes() {
      if (typeof Object.freeze !== 'function') {
        throw new Error('Missing Object.freeze');
      }
      Object.freeze(Object.prototype);
      Object.freeze(Array.prototype);
      Object.freeze(Function.prototype);
    }());

    11.Javascript多维数组扁平化

    下面是将多位数组转化为单一数组的三种不同方法。

    var arr = [[1, 2],[3, 4, 5], [6, 7, 8, 9]];

    期望结果:

    [1, 2, 3, 4, 5, 6, 7, 8, 9]

    解决方案1:使用concat()和apply()

    var newArr = [].concat.apply([], arr);
    // [1, 2, 3, 4, 5, 6, 7, 8, 9]

    解决方案2:使用reduce()

    var newArr = arr.reduce(function(prev, curr) {
      return prev.concat(curr);
    });
    // [1, 2, 3, 4, 5, 6, 7, 8, 9]

    解决方案3:使用 ES6 的展开运算符

    var newArr = [].concat(...arr);
    console.log(newArr);
    // [1, 2, 3, 4, 5, 6, 7, 8, 9]

    12. 函数中如何使用可选参数(包括可选回调函数)

    实例函数中第2个与第3个参数为可选参数

    function example( err, optionA, optionB, callback ) {
            // 使用数组取出arguments
            var args = new Array(arguments.length);
            for(var i = 0; i < args.length; ++i) {
                args[i] = arguments[i];
            };
            
            // 第一个参数为错误参数
            // shift() 移除数组中第一个参数并将其返回
            err = args.shift();
    
            // 如果最后一个参数是函数,则它为回调函数
            // pop() 移除数组中最后一个参数并将其返回
            if (typeof args[args.length-1] === 'function') { 
                callback = args.pop();
            }
            
            // 如果args中仍有元素,那就是你需要的可选参数
            // 你可以像这样一个一个的将其取出:
            if (args.length > 0) optionA = args.shift(); else optionA = null;
            if (args.length > 0) optionB = args.shift(); else optionB = null;
    
            // 像正常一样继续:检查是否有错误
            if (err) { 
                return callback && callback(err);
            }
            
            // 打印可选参数
            console.log('optionA:', optionA);
            console.log('optionB:', optionB);
            console.log('callback:', callback);
    
            /* 你想做的逻辑 */
    
        }
    
        // ES6语法书写更简短
        function example(...args) {
            // 第一个参数为错误参数
            const err = args.shift();
            // 如果最后一个参数是函数,则它为回调函数
            const callback = (typeof args[args.length-1] === 'function') ? args.pop() : null;
    
            // 如果args中仍有元素,那就是你需要的可选参数你可以像这样一个一个的将其取出:
            const optionA = (args.length > 0) ? args.shift() : null;
            const optionB = (args.length > 0) ? args.shift() : null;
            // ... 重复取更多参数
    
            if (err && callback) return callback(err);
    
            /* 你想做的逻辑 */
        }

    推荐教程:《JS教程》

    以上就是JavaScript的技巧的详细内容,更多请关注爱上源码网其它相关文章!

  • 微信
  • 分享
  • 相关标签:js
  • 本文转载于:掘金,如有侵犯,请联系916990011@qq.com删除
    • 上一篇:JS怎么实现简单轮播图特效?(图文详解)
    • 下一篇:箭头函数和普通函数区别

    相关文章

    相关视频

    • js面向对象编程
    • JS文件与PHP文件区别?
    • NodeJs能实现PHP所有的功能吗?
    • js基础知识
    • JavaScript的技巧
    • Node.js queryString模块
    • JavaScript基础篇——了解js
    • 加入 Vue.js 社区

    本文有爱上源码下载完入驻作者发布,如果对您版权造成侵害,可以联系本站站长管理进行维权删除,本站收到维权24小时内进行处理,谢谢您关注23ym.cn!
    本站分享大量程序员技术文章以及对编程开发的初级入门教程,包括图文讲解笔记和高清视频下载~

    重要声明:
    1.本站视频教程,软件及网站源码版权均属于原作者所有,您必须在下载后的24个小时之内,从您的电脑中删除!非法商业用途,后果自负!
    2.本站不保证所提供下载资源的安全性和完整性,仅供下载学习之用!如链接失效或资源含外站广告,请联系客服处理!给予奖励!
    3.本站所有资源来源于用户上传和网络,因此不包含技术服务请大家谅解!本站提供有偿服务!如有侵权请联系在线客服!
    4.如您手中有优质资源或教程,可以自助投稿发布,成功分享后有奖励和额外收入!
    5.如您需要正版微擎模块可联系本站客服,我们有价值30w+商业微擎应用出售微擎坑位和招收代理!
    6.400电话/软著/ICP,EDI许可证/商标特价办理中!
    爱上源码下载网 » JavaScript的技巧

    常见问题FAQ

    从网站下载的源码都有安装教程么?不会安装怎么办?
    本站发布的网站源码和模板资源大部分在压缩包内都有教程,如您不会安装可以联系本站在线技术进行付费安装。
    爱上源码的所有源码都是亲测能正常运行的么?
    本站目前拥有资源10w+,包含整站源码,网站模板,游戏源码,小程序源码,视频教程,破解软件等,每天也在测试更新;因时间和精力有限我们无法对资源进行一一测试,只能保证所分享资源内容无误,希望理解。
    我手中的优质资源可以在你这换钱或者VIP么?
    爱上源码支持投稿,欢迎发布您手中的优质资源进行售卖;本站VIP支持免费获取,目前邀请10人注册爱上源码即可免费获取VIP。
    爱上源码除了资源分享还有其他业务没?
    【价值30W+微擎模块出售正版商业微擎坑位及招收代理,详情咨询本站客服!】我们团队目前运营并推广几套商业化saas智能小程序系统能满足大部分小程序开发需求,并由SaaS和独立部署版商城小程序系统;另外销售400电话,各种ICP/EDI资质证书办理,软著和商标注册服务等。

    发表评论

    • 28会员总数(位)
    • 35644资源总数(个)
    • 0本周发布(个)
    • 0 今日发布(个)
    • 543稳定运行(天)

    提供最优质的资源集合

    开通VIP 源码下载