React学习笔记(一):ES6语法学习(1):变量、函数、数组

前言

《React学习笔记》系列,旨在总结自己学习React的过程,也希望能给刚接触React框架的同学带来一点有益的启发。

本系列笔记,初步将内容规划为以下几个部分:
一、ES6语法学习
二、环境搭建:Babel + Webpack
三、React简介和JSX语法
四、React组件
五、React数据流
六、受控组件与非受控组件
七、React组件生命周期

那好,接下来我们先为学习React做一下知识储备,开始学习ES6的一些语法。


一、ES6简介

提到ES6的学习,先推荐阮一峰大神的 《ECMAScript 6 入门》,一本开源电子书,学习ES6的好手册。

ES6标准发布于2015年6月,因此也叫ES2015。

ES6中有很多新的语法特性,本文只择出一些 常用的React中会使用到的 新特性进行介绍。

  1. let和const变量
  2. 变量的解构赋值
  3. 箭头函数
  4. 数组的新方法
  5. 对象的新特性
  6. Promise和async
  7. class
  8. Module

注:每种新特性只介绍简单用法,不包全面只包实用,不求理解原理只求快速上手。

二、let和const变量

2.1 let

ES5中变量用var声明,只有全局作用域和函数作用域,没有块级作用域。

ES6中用let来定义块级作用域变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效

所谓的块级作用域,就是由{}包裹的区域,比如我们常用的for循环,if判断。

{
  var a = 10;
  let b = 20;
}

console.log(a); // 10
console.log(b); // 报错:a is not defined.
复制代码

以后的for循环,我们可以使用let来定义变量,这样变量只在for循环体内有效,在循环体外引用就会报错。

for (let i = 0; i < 10; i++) {
  // ...
}

console.log(i); // 报错:i is not defined
复制代码

2.2 const

const声明一个只读的常量。一旦声明,常量的值就不能改变。

const a = 10;
a = 20; 

console.log(a); // 报错:TypeError: Assignment to constant variable.
复制代码

const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。

const a; // 报错:SyntaxError: Missing initializer in const declaration
复制代码

一般来,说函数的定义都是不变的,所以今后的函数一律用const定义。

const fun = function () {
    // ...
}
复制代码

注意一点:

letconst定义的变量都 不存在变量声明提升。也就是说,今后你想使用一个变量,必须先声明后使用了。这样可以避免一些意料之外的错误。

console.log(a); // 报错
let a = 10;
复制代码

三、变量的解构赋值

3.1 数组和对象的解构赋值

解构赋值,字面意思很容易理解,分解结构再进行赋值。

以前想得到数组或者对象中的某个值,数组需要使用 下标索引,对象要使用 点语法

var arr = [10, 20, 30];
var a = arr[0];
var b = arr[1];
var c = arr[2];

var obj = {
    name:"小明",
    age:18,
    sex:"男"
};
var name = obj.name;
var age = obj.age;
var sex = obj.sex;
复制代码

ES6中,允许从数组中提取值,按照对应位置,对变量赋值。对象也是一样。

解构赋值语法是一个 Javascript 表达式,这使得可以将 值从数组属性从对象 提取到不同的变量中。 ---火狐MDN

let [a, b, c] = [10, 20, 30];
console.log(a); // 10
console.log(b); // 20
console.log(v); // 30

let {name, age, sex}  = {name:"小明", age:18, sex:"男"};
console.log(name); // 小明
console.log(age);  // 18
console.log(sex);  // 男
复制代码

注意,数组的解构赋值使用的是方括号[],对象的解构赋值使用的是大括号{}

解构赋值有个很大的用处,就是用在函数的参数上。

function add([x, y]){
  return x + y;
}

add([1, 2]); // 3

function ajax({url, method, })
复制代码

3.2 ...操作符

是的,你没看错,这三个点...是一个操作符,不可分割。

...作为操作符,有两种用途。

一种叫做扩展操作符,英文Spread Operator;另一种叫做剩余操作符,英文(Rest Parameters。两者可以互为逆运算。

  • 扩展操作符

先说说扩展操作符,可以 将数组或者对象里面的值展开

let arr = [10, 20, 30]
console.log(...arr) // 1 2 3
复制代码

用在对象身上,一般用来 创建一个对象的副本,仅仅改变原对象的个别属性,不影响原对象

// 这是去年的小明,17岁
let obj = {
    name: "小明",
    age: 17,
    sex: "男"
}

// 这是今年的小明,长了一岁
let obj2 = {
    ...obj,
    age:18
}
console.log(obj);  // Object { name: "小明", age: 17, sex: "男" }
console.log(obj2); // Object { name: "小明", age: 18, sex: "男" }
复制代码
  • 剩余操作符

扩展操作符相反,剩余操作符将多个值收集为一个变量,而扩展操作符是将一个数组或对象扩展成多个值。

回想上面数组的解构赋值,如果用来接收值的变量不够,那么数组中剩下的值就拿不到了。

// 数组中只有10,20,30这三个元素被变量a, b, c接走了,剩下的40,,50,60没人管
let [a, b, c] = [10, 20, 30, 40, 50 ,60]; 

// 使用剩余操作符,让c接走剩下的元素
// 现在,数组中的10,20被变量a, b接走了,剩下的打包成一个数组给了c
let [a, b, ...c] = [10, 20, 30, 40, 50 ,60]; 
console.log(c); // [30, 40, 50, 60]
复制代码

需要注意的是,既然叫做剩余操作符,那么只能打包剩下的元素...出现在其他位置就会报错。

let [a, ...b, c] = [10, 20, 30, 40, 50 ,60]; // 报错
复制代码

四、箭头函数

4.1 参数默认值

ES6允许给形参设置默认值,直接写在形参的后面。

function log(x, y = 'World') {
  console.log(x, y);
}

log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello
复制代码

4.2 箭头函数

ES6允许使用“箭头”=>定义函数。可以看作是省略了function关键字。
注意=>是一个整体,中间不能有空格。

const add = (a, b) => {
    reutrn a + b;
};

// 等同于
cosnt add = function (a, b) {
  return a + b;
};

add(10, 20); // 30
复制代码

如果函数体只有一条语句并且是return语句,不需要写大括号{},还可以省略return。 反之,如果函数体有多条语句必须使用{}包裹。

cosnt add = (a, b) => a + b;
复制代码

如果函数体需要换行,必须使用{}包裹。

var add = (a, b) => {
    return a + b;
}
复制代码

如果函数的参数只有一个,可以省略()

const fun = v => v;

// 等价于
const fun = function(v){
    return v;
}
复制代码

如果函数返回值为一个对象,必须使用()包裹,否则会报错。因为对象的{}会被认为是代码块。

// 报错
const fun = id => { id: id, name: "Temp" };

// 不报错
const fun = id => ({ id: id, name: "Temp" });

复制代码

4.3 箭头函数的this

我们知道,在JavaScript这门神奇的语言中,只要函数还没有被调用,你永远也不知道this到底指向谁!

关于this指向的问题,这里不再赘述,还没弄明白的同学可以找找相关资料学习下再来看下面的内容。

到了箭头函数,关于this的指向问题,又多了一种情况。

箭头函数没有自己的this, 它的this是继承而来的。也就是说,箭头函数的this在定义函数的时候就能够确定,并且不会改变

let a = 10;
let obj = {
    a :20,
    fn: ()=> {
        console.log(this.a);
    }
}

obj.fn(); // 10 
复制代码

上面例子中,为什么打印结果是10呢? 我们说过,箭头函数中的this是继承而来,它的上一级是obj,也就是说箭头函数中的this其实是objthis,那么objthis又是谁呢?毫无疑问是window对象,所以最终打印出来的a的值其实是window对象下的变量a

以前用callapplybind能改变this的指向,到了箭头函数这里,不好使!

let a = 10;
let obj = {
    a :20,
    fn: ()=> {
        console.log(this.a);
    }
}

obj.fn.call(obj);   // 10
obj.fn.apply(obj);  // 10
obj.fn.bind(obj)(); // 10
复制代码

注意,这里的环境是浏览器环境,全局对象为window。若在node环境中,打印结果为undefined

关于箭头函数的使用,总结下需要注意的点:

(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。

上面四点中,第一点尤其值得注意。this对象的指向是可变的,但是在箭头函数中,它是固定的。

五、数组的新方法

下面这些方法并不都是ES6中的新特性,大部分都是ES5中的方法。

因为这些方法在React中很常用,所以在此罗列一下。

5.1 Array.map()

map这个单词不仅有“地图”的意思,在计算机技术中更常用的意思是“映射”。

Array.map()方法返回一个新的数组,新数组的每一项都是原数组的映射。简单理解就是,map()方法的参数是一个函数,原数组中的每一项会经过这个函数处理后返回,组成一个新的数组。

// 返回一个数组,数组中元素为原来数组的两倍:
let arr = [4, 9, 16, 25];

// newArr用来接收返回的新数组
//item参数就是原数组中的元素,每次遍历对它进行操作
let newArr = arr.map((item)=>{
        return item * 2;
    })

console.log(newArr); // [ 8, 18, 32, 50 ]
复制代码

5.2 Array.filter()

filter为“过滤器”的意思。很明显,filter()方法是对数组进行一些“过滤”操作。

filter()的参数同样是一个函数,表示对原数组中的元素进行的操作,用火狐MDN的说法,叫做“测试”,通过测试的元素就会被返回,没有通过的就被“过滤”掉了。通过测试的元素会返回成一个新数组。

// 有这么一个数组,我们需要筛选一下年龄大于(包括)18岁的学生去参加一项社会活动
let students = [
        {name:"小明", age:18},
        {name:"小强", age:15},
        {name:"小刚", age:19},
        {name:"壮壮", age:20},
        {name:"小凡", age:14},
        {name:"小光", age:16}
    ]

// 使用filter()
// item就是原来数组的每个学生
// 当某个学生通过我们的“测试”(item.age>=18)时,其检测结果为true,那么就返回这一项
// 检测结果为false的,就不会返回
let newStudents = students.filter((item)=>{
    return item.age >= 18;
});

console.log(newStudents);
/* [ { name: '小明', age: 18 },
  { name: '小刚', age: 19 },
  { name: '壮壮', age: 20 } ]
 */
复制代码

5.3 Array.forEach

一个新的遍历数组的方法。可以在一定程度上替代原来的for循环语法。

let arr = [1, 2, 3, 4, 5, 6];

for(let i=0; i<arr.length; i++){
    console.log(arr[i]);
}

arr.forEach((item,index)=>{
    console.log(item);
})
复制代码

forEach()有缺点。
不能使用break语句中断循环:
forEach()中使用break会报错,在for循环中使用break会终止循环。

不能使用return语句返回到外层函数:
forEach()中使用return没有任何作用,在for循环中使用return会打断循环,并且打断同层级下面语句的执行。

let arr = [1, 2, 3, 4, 5, 6];

arr.forEach((item,index)=>{
    if(item== 4){
        return;
    }
    console.log(item);
})

for(let i=0; i<arr.length; i++){
    if(arr[i]== 4){
        return;
    }
    console.log(arr[i]);
}
复制代码

5.4 for-of

ES6强烈推荐的方法。

这是最简洁、最直接的遍历数组元素的语法,避开了for-in循环的所有缺陷。 并且,与forEach()不同的是,它可以正确响应breakcontinuereturn语句。

for-of可以遍历数组,字符串,类数组对象和其他集合。

let arr = [10, "hello", 20, {a: 20}];
let string = 'hello world';

// v就是数组中的每一项元素
for(let v of arr){
    console.log(v);
}

for(let v of string){
    console.log(v);
}

// 结果
10
hello
20
{ a: 20 }
h
e
l
l
o

w
o
r
l
d
复制代码

注意,for-of不支持遍历对象。这点上还是要使用for-in,毕竟这也是它的本职工作。

5.5 Array.from()

Array.from()方法用于将类数组对象转为真正的数组。

let arrayLike = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3
};

// ES5的写法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']

// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
复制代码

小结

本文总结了ES6中出现的新特性,包括变量、解构赋值、箭头函数、数组。

其中数组这一章节中大部分都是ES5中的方法,但在React中很常用,所以算是“新瓶装老酒”了。

转载于:https://juejin.im/post/5b1dd827e51d4506d33d079d

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值