zoukankan      html  css  js  c++  java
  • JavaScript与TypeScript总结

    一、ES6标准

    1.let、var、const

    ①let声明的变量只在let命令所在的代码块内有效。var声明的变量在全局都有效,代码块内会收到全局其他地方重复声明的影响。const将声明一个无法重复赋值的变量。

    ②var的变量提升:变量可以在声明之前使用,值为undefined。let不允许变量提升。

    ③“暂时性死区”(temporal dead zone,简称 TDZ):如果区块中存在letconst命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。

    let不允许在相同作用域内,重复声明同一个变量。var可以。

    2.变量的解构赋值

    ①基本用法:

    let [a, b, c] = [1, 2, 3];

    ②如果解构不成功,变量的值就等于undefined

    ③解构赋值允许指定默认值。

    let [foo = true] = [];
    foo // true
    
    let [x, y = 'b'] = ['a']; // x='a', y='b'
    let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'

    ④字符串的解构赋值:

    const [a, b, c, d, e] = 'hello';
    a // "h"
    b // "e"
    c // "l"
    d // "l"
    e // "o"

    类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。

    let {length : len} = 'hello';
    len // 5

    ⑤使用解构赋值交换变量的值

    let x = 1;
    let y = 2;
    
    [x, y] = [y, x];

    ⑥遍历遍历 Map 结构

    const map = new Map();
    map.set('first', 'hello');
    map.set('second', 'world');
    
    for (let [key, value] of map) {
      console.log(key + " is " + value);
    }

     3.函数的扩展

    ①利用参数默认值,可以指定某一个参数不得省略。

    function throwIfMissing() {
      throw new Error('Missing parameter');
    }
    
    function foo(mustBeProvided = throwIfMissing()) {
      return mustBeProvided;
    }
    
    foo()
    // Error: Missing parameter

    ②ES6 引入 rest 参数(形式为...变量名),用于获取函数的多余参数。

    function add(...values) {
      let sum = 0;
    
      for (var val of values) {
        sum += val;
      }
    
      return sum;
    }
    
    add(2, 5, 3) // 10

    注意,rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。

    ③严格模式

    'use strict'

    ④name属性:调用XXX.name将返回这个XXX函数的函数名。

    ⑤嵌套的箭头函数

    function insert(value) {
      return {into: function (array) {
        return {after: function (afterValue) {
          array.splice(array.indexOf(afterValue) + 1, 0, value);
          return array;
        }};
      }};
    }
    
    insert(2).into([1, 3]).after(1); //[1, 2, 3]
    let insert = (value) => ({into: (array) => ({after: (afterValue) => {
      array.splice(array.indexOf(afterValue) + 1, 0, value);
      return array;
    }})});
    
    insert(2).into([1, 3]).after(1); //[1, 2, 3]

    但是,一旦不注意,可读性就会呈几何级下降。

    ⑥尾函数优化

    函数执行的时候有一个函数栈,在A函数中执行B函数,A函数的执行结果和调用点都会保存在函数栈中,因为B函数调用完会还得返回去执行A函数。当A函数的最后一步操作是执行B函数的时候,显而易见的,可以释放A函数在函数栈上的资源了。

    典型应用就是,递归函数,只要递归函数的最后一步是执行其本身,那么就会使爆栈的几率大大降低。看一个Fibonacci 数列的例子:

    function Fibonacci (n) {
      if ( n <= 1 ) {return 1};
    
      return Fibonacci(n - 1) + Fibonacci(n - 2);
    }
    
    Fibonacci(10) // 89
    Fibonacci(100) // 堆栈溢出
    Fibonacci(500) // 堆栈溢出
    function Fibonacci2 (n , ac1 = 1 , ac2 = 1) {
      if( n <= 1 ) {return ac2};
    
      return Fibonacci2 (n - 1, ac2, ac1 + ac2);
    }
    
    Fibonacci2(100) // 573147844013817200000
    Fibonacci2(1000) // 7.0330367711422765e+208
    Fibonacci2(10000) // Infinity

    遗憾的是,是否进行尾函数优化,是由编程语言跟编译器决定的。ES6支持,但是比如JAVA就不支持这个东西(JAVA不建议使用递归)。

    4.数组的扩展

    ①扩展运算符“...”

    将一个数组转为用逗号分隔的参数序列。

    console.log(1, ...[2, 3, 4], 5)
    // 1 2 3 4 5
    // 可与其他参数一起使用
    
    [...document.querySelectorAll('div')]
    // [<div>, <div>, <div>]
    
    
    function add(x, y) {
      return x + y;
    }
    
    const numbers = [4, 38];
    add(...numbers) // 42

    注意,扩展运算符如果放在括号中,JavaScript 引擎就会认为这是函数调用。如果这时不是函数调用,就会报错。

    由于扩展运算符可以展开数组,所以不再需要apply方法,将数组转为函数的参数了。

    还可以赋值数组:const a2 = [...a1];

    还可以合并数组:const a4 = [...a1, ...a2];

    还可以将字符串转为真正的数组:const a5 = [...'hello'] (任何定义了遍历器Iterator接口的对象,都可以用扩展运算符转为真正的数组。)

    Map 和 Set 结构,Generator 函数都可以使用扩展运算符,比如 Map 结构:

    let map = new Map([
      [1, 'one'],
      [2, 'two'],
      [3, 'three'],
    ]);
    
    let arr = [...map.keys()]; // [1, 2, 3]

    5.对象的扩展

    ①ES6 允许直接写入变量和函数,作为对象的属性和方法(只要你有一个引用,你甚至可以包括整个宇宙)。

    let birth = '2000/01/01';
    
    const Person = {
    
      name: '张三',
    
      //等同于birth: birth
      birth,
    
      // 等同于hello: function ()...
      hello() { console.log('我的名字是', this.name); }
    
    };
    function getPoint() {
      const x = 1;
      const y = 10;
      return {x, y};
    }
    
    getPoint()
    // {x:1, y:10}

    ②属性遍历

    ES6 一共有 5 种方法可以遍历对象的属性。官方推荐使用Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名。

    遍历对象的键名,都遵守同样的属性遍历的次序规则。

    • 首先遍历所有数值键,按照数值升序排列。
    • 其次遍历所有字符串键,按照加入时间升序排列。
    • 最后遍历所有 Symbol 键,按照加入时间升序排列。

    Object.assign方法

    Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。但是,Object.assign方法实行的是浅拷贝,而不是深拷贝。

    const target = { a: 1 };
    
    const source1 = { b: 2 };
    const source2 = { c: 3 };
    
    Object.assign(target, source1, source2);
    target // {a:1, b:2, c:3}

    同样的操作也可以进行对象克隆

    function clone(origin) {
      let originProto = Object.getPrototypeOf(origin);
      return Object.assign(Object.create(originProto), origin);
    }

    为对象添加属性

    class Point {
      constructor(x, y) {
        Object.assign(this, {x, y});
      }
    }

    为对象添加方法

    Object.assign(SomeClass.prototype, {
      someMethod(arg1, arg2) {
        ···
      },
      anotherMethod() {
        ···
      }
    });
    
    // 等同于下面的写法
    SomeClass.prototype.someMethod = function (arg1, arg2) {
      ···
    };
    SomeClass.prototype.anotherMethod = function () {
      ···
    };

    6.Symbol变量

    ①Singleton 模式

    // mod.js
    const FOO_KEY = Symbol.for('foo');
    
    function A() {
      this.foo = 'hello';
    }
    
    if (!global[FOO_KEY]) {
      global[FOO_KEY] = new A();
    }
    
    module.exports = global[FOO_KEY];
    const a = require('./mod.js');
    console.log(a.foo);

    这同时也是全局变量的设置方案,唔。

    7.Set 变量

    ①成员的值都是唯一的,没有重复的值。四大方法:add、delete、has、clear。

    Set函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化。

    // 例一
    const set = new Set([1, 2, 3, 4, 4]);
    [...set]
    // [1, 2, 3, 4]

    ③利用Set给数组去重

    // 去除数组的重复成员
    [...new Set(array)]

    给字符串去重

    [...new Set('ababbc')].join('')
    // "abc"

    Array.from方法可以将 Set 结构转为数组。这就提供了去除数组重复成员的另一种方法。

    function dedupe(array) {
      return Array.from(new Set(array));
    }
    
    dedupe([1, 1, 2, 3]) // [1, 2, 3]

    8.Proxy

    Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程。

    其实就是一个拦截器,按照官方的描述,更像是一个C++的运算符重载,跟C#的set构造器有异曲同工之妙。它几乎可以作用于所有对象的行为,不仅仅是传参。(或许可以拿来弄一个enum)

    一个技巧是将 Proxy 对象,设置到object.proxy属性,从而可以在object对象上调用。  var object = { proxy: new Proxy(target, handler) };

    实现数组读取负数的索引

    function createArray(...elements) {
      let handler = {
        get(target, propKey, receiver) {
          let index = Number(propKey);
          if (index < 0) {
            propKey = String(target.length + index);
          }
          return Reflect.get(target, propKey, receiver);
        }
      };
    
      let target = [];
      target.push(...elements);
      return new Proxy(target, handler);
    }
    
    let arr = createArray('a', 'b', 'c');
    arr[-1] // c

    9.JavaScript Array 对象的方法

    常用方法:

    push()  向数组的末尾添加一个或更多元素,并返回新的长度。

    concat()  连接两个或更多的数组,并返回结果(a.concat(b))。

    值得注意的是,若a是空的,就不能直接concat。

    10.=== 和 ==的区别

    ===严格比较,类型不同就是不同;==会将两边转换成值再比较,比如string和int,1和‘1’是相等的。

  • 相关阅读:
    How to create jar for Android Library Project
    Very large tabs in eclipse panes on Ubuntu
    64bit Ubuntu, Android AAPT, R.java
    Linux(Ubuntu)下如何安装JDK
    Configure xterm Fonts and Colors for Your Eyeball
    建立、配置和使用Activity——启动其他Activity并返回结果
    建立、配置和使用Activity——使用Bundle在Activity之间交换数据
    建立、配置和使用Activity——启动、关闭Activity
    建立、配置和使用Activity——Activity
    异步任务(AsyncTask)
  • 原文地址:https://www.cnblogs.com/chrisweiii/p/10553934.html
Copyright © 2011-2022 走看看