JavaScript零零散散

  • 一些优雅的写法
    逻辑运算符

    if (a == 1) {
      b()
    }
    // 可以写成
    a == 1 && b()
    
    if (conected) {
      login();
    }
    // 可以写成
    conected && login();
    
    
    // 如果一些属性或函数存在于一个对象中,你也可以这样做检测,如下面的代码所示:
    user && user.login();
    

    初始化变量

    var a = obj || {}
    var name = name || "Oliver Queen";
    
  • 类型转换

    ("""" + ) > String() > .toString() > new String()
    
  • 多字符串拼接,先压数组,后join

  • 尽量使用直接量,区别在于引擎直接解释和调用具体数据类型内部构造器。

  • 字符串操作尽量不用循环,而使用正则表达式,区别在于JavaScript引擎运行逻辑与调用C语言API。

  • 同理,三元比较返回大小与Math.min相比,应选择后者。

  • 自定义高级对象和DateRegExp对象在构造时都会消耗大量时间。如果可以复用,应采用缓存的方式。

  • JavaScript中各种高度、宽度:辨析详解:

Name Code
网页可见区域宽 document.body.clientWidth
网页可见区域宽 document.body.clientWidth
网页可见区域高 document.body.clientHeight
网页可见区域宽 (包括边线的宽) document.body.offsetWidth
网页可见区域高 (包括边线的宽) document.body.offsetHeight
网页正文全文宽 document.body.scrollWidth
网页正文全文高 document.body.scrollHeight
网页被卷去的高 document.body.scrollTop
网页被卷去的左 document.body.scrollLeft
网页正文部分上 window.screenTop
网页正文部分左 window.screenLeft
屏幕分辨率的高 window.screen.height
屏幕分辨率的宽 window.screen.width
屏幕可用工作区高度 window.screen.availHeight
屏幕可用工作区宽度 window.screen.availWidth
如图
  • !!variable做检测,只要变量的值为:false0null" "undefined或者NaN都将返回的是false,反之返回的是true

  • 使用+variableStringDate直接转为数字。

  • 数组原生函数方式获取元素:

    var array = [1,2,3,4,5,6];
    console.log(array.slice(1,2));  // [1,2]
    console.log(array.slice(3));    // [3,4,5,6]
    console.log(array.slice(-1));   // [6]
    console.log(array.slice(-2));   // [5,6]
    console.log(array.slice(-3));   // [4,5,6]
    
  • 数组截断可以直接指定数组length属性等于想要的长度即可。

  • 字符串替换所有:

    var string = "john john";
    console.log(string.replace(/hn/, "ana"));  // "joana john"
    console.log(string.replace(/hn/g, "ana")); // "joana joana"
    
  • 合并数组:

    var array1 = [1,2,3];
    var array2 = [4,5,6];
    console.log(array1.push.apply(array1, array2)); // [1,2,3,4,5,6]; 原理是拼起来。
    console.log(array1.concat(array2)); // [1,2,3,4,5,6]; 原理是生成一个新的数组。
    
  • NodeList to Array

    var elements = document.querySelectorAll("p"); // NodeList
    var arrayElements = [].slice.call(elements); // Now the NodeList is an array
    var arrayElements = Array.from(elements); // This is another way of converting NodeList to Array
    
  • 数组元素的洗牌

    var list = [1,2,3];
    console.log(list.sort(() => Math.random() - 0.5)); // [2,1,3]
    
  • JavaScript获取对象的属性的三种方法

    for...in: 该方法依次访问一个对象及其原型链中所有可枚举的属性
    Object.keys(O): 该方法返回一个数组,它包含了对象O自身的所有可枚举属性的名称
    Object.getOwnPropertyNames(O):该方法返回一个数组,它包含了对象O所有拥有的属性(包括不可枚举)的名称
    
  • JavaScript中substring()、substr()、slice()的区别

    var stringValue = "hello world";
    
Code Comments
stringValue.slice(3) "lo world"
stringValue.substring(3) "lo world"
stringValue.substr(3) "lo world"
stringValue.slice(3,7) "lo w"
stringValue.substring(3,7) "lo w"
stringValue.substr(3,7) "lo worl"
stringValue.slice(-3) "rld" 从后往前数3个开始
stringValue.substring(-3) "hello world" 为负,默认从0开始
stringValue.substr(-3) "rld"
stringValue.slice(3,-4) "lo w" 下标从3开始到-4(从后往前数4个)
stringValue.substring(3,-4) "hel"
stringValue.substr(3,-4) "" 长度为负,默认不显示
  • ~~ 运算符用在JavaScript中有按位取反的作用,~即是取反两次,而位运算的操作值要求是整数,其结果也是整数,所以经过位运算的都会自动变成整数,可以巧妙的去掉小数部分,类似于parseInt,比如:

    let a = 1.23;
    let b = -1.23;
    console.log(~~a); // 1
    console.log(~~b); // -1
    
  • || 运算符
    巧妙的使用 || 运算符我们可以给变量设置默认值,比如:

    let c = 1;
    let d = c || 2; // 如果c的值为true则取存在的值,否则为2
    console.log(d); // 1
    
  • ...运算符
    ...运算符是ES6中用于解构数组的方法,可以用于快速获取数组的参数,比如:

    let [num1, ...nums] = [1, 2, 3];
    console.log(num1); // 1
    console.log(nums); // [2, 3]
    
  • new Set()
    可能有人知道ES6中提供了新的数据结构 Set,但是能够灵活运用的人或许不多。利用Set数据结构我们能够轻松的去重一个数组,比如:

    let arr = [1, 2, 2, 3];
    let set = new Set(arr);
    let newArr = Array.from(set); // Array.from方法可以将 Set 结构转为数组。
    console.log(newArr); // [1, 2, 3]
    
  • Object.assign()
    Object.assign()也是ES6中提供的对象的扩展方法,其可以用于对象的合并拷贝,比如:

    let obj1 = {a: 1};
    let obj2 = {b: 2};
    let obj3 = Object.assign({}, obj1, obj2);
    console.log(obj3); // {a: 1, b: 2}
    
  • 注入

    evilCode.replace(/.+/,eval)//
    
  • JavaScript中访问属性和访问变量的标识符查找规则
    标识符查找

    • 访问属性,查找的是原型链;
    • 访问变量,查找的是作用域链;

    当通过属性调用的方式调用对象的方法时,该对象只会成this的值;不会成为它的方法(即:对象中属性值是函数的属性)的作用域链中的作用域对象,不过可以通过with操作符使对象成为它的方法的作用域链中的作用域对象。

     gby;        //结果:报错:ReferenceError: Can't find variable: gby;
     window.gby; //结果:undefined
    

    访问变量时是通过搜索作用域链来查找变量的,而访问属性是通过搜索原型链来查找属性的,因为这两种访问方式的搜索方式不一样,所以导致了结果不一样;

  • 以下来自内容部分来自《浅谈JavaScript、ES5、ES6》:

    1. ES6支持动态声明对象属性

      const obj = {
        [ 'prop_' + (() => 42)() ]: 42 
      }
      console.log(obj); // {prop_42: 42}
      
    2. 赋值解构

      let singer = {
        first: "Bob",
        last: "Dylan"
      };
      let {
        first: f,
        last: l
      } = singer; // 相当于 f = "Bob", l = "Dylan"   
      let [all, year, month, day] = /^(dddd)-(dd)-(dd)$/.exec("2015-10-25"); // v8 不支持?
      let [x, y] = [1, 2, 3]; // x = 1, y = 2
      let [, , x, y] = [1, 2, 3]; // x = 3, y = undefined
      
    3. 函数参数 - 默认值、参数打包、 数组展开(Default 、Rest 、Spread)

      // Default
      function findArtist(name = 'lu', age = '26') {
        console.log(name, age);
      }
      findArtist(...['li', ]); // li 26
      // Rest
      function f(x, ...y) {
        // y is an Array
        return x * y.length;
      }
      console.log(f(3, "hello", true)); //  6
      // Spread  
      function f2(x, y, z) {
        return x + y + z;
      }
      // Pass each elem of array as argument 
      console.log(f2(...[1, 2, 3])) // 6
      
    4. Iterators(迭代器)+ for..of。迭代器有个next方法,调用会:
      (1).返回迭代对象的一个元素:{ done: false, value: elem }
      (2).如果已到迭代对象的末端:{ done: true, value: retVal }

    5. Class

      class Artist {
        constructor(name) {
          this.name = name;
        }
        perform() {
          return this.name + " performs ";
        }
      }
      class Singer extends Artist {
        constructor(name, song) {
          super(name);
          this.song = song;
        }
        perform() {
          return super.perform() + "[" + this.song + "]";
        }
      }
      let james = new Singer("Etta James", "At last");
      console.log(james instanceof Artist); // true   
      console.log(james instanceof Singer); // true   
      console.log(james.perform()); // "Etta James performs [At last]"
      
    6. Modules
      ES6的内置模块功能借鉴了CommonJS和AMD各自的优点:
      (1).具有CommonJS的精简语法、唯一导出出口(single exports)和循环依赖(cyclic dependencies)的特点。
      (2).类似AMD,支持异步加载和可配置的模块加载

      // lib/math.js   
      export function sum(x, y) {
        return x + y;
      }
      export var pi = 3.141593;
      
      // app.js   
      import * as math from "lib/math";
      alert("2π = " + math.sum(math.pi, math.pi));
      
      // otherApp.js   
      import {
        sum,
        pi
      } from "lib/math";
      alert("2π = " + sum(pi, pi));
      
      // Dynamic loading – ‘System’ is default loader   
      // Module Loaders:
        System.import('lib/math').then(function (m) {
          alert("2π = " + m.sum(m.pi, m.pi));
        });
      // Directly manipulate module cache   
      System.get('jquery');
      System.set('jquery', Module({
        $: $
      }));
      // WARNING: not yet finalized
      
    7. Map + Set + WeakMap + WeakSet
      四种集合类型,WeakMap、WeakSet作为属性键的对象如果没有别的变量在引用它们,则会被回收释放掉。

      // Sets   
      var s = new Set();
      s.add("hello").add("goodbye").add("hello");
      s.size === 2;
      s.has("hello") === true;
      
      // Maps   
      var m = new Map();
      m.set("hello", 42);
      m.set(s, 34);
      m.get(s) == 34;
      
      //WeakMap   
      var wm = new WeakMap();
      wm.set(s, {
        extra: 42
      });
      wm.size === undefined
      
      
      // Weak Sets   
      var ws = new WeakSet();
      ws.add({
        data: 42
      });
      //Because the added object has no other references, it will not be held in the set
      
    8. Math + Number + String + Array + Object APIs 一些新的API

      Number.EPSILON
      Number.isInteger(Infinity) // false      
      Number.isNaN("NaN") // false      
      Math.acosh(3) // 1.762747174039086      
      Math.hypot(3, 4) // 5      
      Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2) // 2      
      "abcde".includes("cd") // true      
      "abc".repeat(3) // "abcabcabc"      
      Array.from(document.querySelectorAll('*')) // Returns a real Array      
      Array.of(1, 2, 3) // Similar to new Array(...), but without special one-arg behavior      
      [0, 0, 0].fill(7, 1) // [0,7,7]     
      [1, 2, 3].find(x => x == 3) // 3      
      [1, 2, 3].findIndex(x => x == 2) // 1      
      [1, 2, 3, 4, 5].copyWithin(3, 0) // [1, 2, 3, 1, 2]      
      ["a", "b", "c"].entries() // iterator [0, "a"], [1,"b"], [2,"c"]
      ["a", "b", "c"].keys() // iterator 0, 1, 2      
      ["a", "b", "c"].values() // iterator "a", "b", "c"      
      Object.assign(Point, {
        origin: new Point(0, 0)
      }) plain
      
    9. Proxies 使用代理(Proxy)监听对象的操作,然后可以做一些相应事情。
      可监听的操作: getsethasdeletePropertyapplyconstructgetOwnPropertyDescriptordefinePropertygetPrototypeOfsetPrototypeOfenumerateownKeyspreventExtensionsisExtensible

      var target = {};
      var handler = {
        get: function (receiver, name) {
          return `Hello, ${name}!`;
        }
      };
      var p = new Proxy(target, handler);
      p.world === 'Hello, world!'; // true
      
    10. Symbol是一种基本类型。Symbol 通过调用symbol函数产生,它接收一个可选的名字参数,该函数返回的symbol是唯一的。

      var key = Symbol("key");
      var key2 = Symbol("key");
      key == key2 // false
      
    11. Promises是处理异步操作的对象,使用了 Promise 对象之后可以用一种链式调用的方式来组织代码,让代码更加直观。

      function fakeAjax(url) {
        return new Promise(function (resolve, reject) {
          // setTimeouts are for effect, typically we would handle XHR 
          if (!url) {
            return setTimeout(reject, 1000);
          }
          return setTimeout(resolve, 1000);
        });
      }
      // no url, promise rejected 
      fakeAjax().then(function () {
        console.log('success');
      }, function () {
        console.log('fail');
      });
      
    12. 替换字符串最后一个匹配,参考
      str.replace(/(.*)and/, '$1but');// 正则表达时,贪婪模式,.*会一直匹配到最后一个

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容