语法糖(Syntactic sugar),是指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会,本篇将介绍几个react常用的几个ES6语法糖。
箭头函数
箭头函数是指使用 '=>' 来定义函数。
正常的Function函数定义如下:
var myFun = function(){
// some code...
}
等价于箭头函数定义:
var myFun = () => {
// some code...
}
带一个参数的箭头函数定义:
var myFun1 = (singleParam) => {
console.log(singleParam); // 打印 singleParam
}
myFun1("singleParam");
带 N个参数时的箭头函数定义:
var myFun2 = (...rest) => {
console.log(rest); // 打印 ["1", "2", "3"]
}
myFun2("1", "2", "3");
当箭头函数需要返回一个对象数据格式时,请加上括号()或 使用return:
var myFun4 = () => ({
id: 1
});
// 等价于
var myFun4 = () => {
return {
id: 1
};
};
箭头函数设置带默认值的参数:
var myFun5 = (s = 'hello', i = 0, [a, b] = [1, 2], c = {x: a+b}) => {
console.log(s, i, a, b, c); // 打印 hello 0 1 2 {x: 3}
}
myFun5();
箭头函数没有自己的this, arguments, super, 或者 new。例如:
var myFun6 = () => {
return this;
};
console.log(myFun6()); // 打印 undefined
但是,如果上面的myFun6代码是嵌套在其它Function函数或class类中,此时this为该Function函数或类的自身而不是undefined。同样,箭头函数使用call()时也要特别注意,由于没有this,故call()的第一个参数会被忽略:
var myFun7 = {
base: 1,
add: function(a) {
// 由于箭头函数没有this,此处this.base返回的是往上最近一层带base或this.base的值,此处为 1
var f = v => v + this.base;
return f(a);
},
addThruCall: function(a) {
var b = {
base: 2
};
var f = v => v + this.base;
return f.call(b, a); // f无法把自身结构赋值给b,因此第一个参数b会被忽略,此时等同于f(a);
},
addFunCall: function(a) {
var b = {
base: 2
};
var f = function(v) {
return(v + this.base);
}
return f.call(b, a); // f可以自身结构赋值给b,即由b调用f的方法,所以此处this.base为2
}
};
console.log(myFun7.add(1)); // 打印 2
console.log(myFun7.addThruCall(1)); // 打印 2
console.log(myFun7.addFunCall(1)); // 打印 3
尽量不要通过argument获取参数,它会获取到最外层的arguments:
function myFun8(n) {
var f = (a = 1) => arguments[0] + n; // 此处获取到的是最外层function的入参3,故结果为3+3
return f(1);
}
console.log(myFun8(3)); // 6
类class
class表示声明一个实例,当遇到多个实例声明和相互调用时,记得一定要先声明后调用。在声明的结构体里,包括一个constructor函数,用于获取入参。如声明一个Person实例:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
// Getter
get getAge() {
this.addOneAge();
return this.age;
}
// Static
static sayHello(name) {
console.log("Hello" + name);
}
// Method
addOneAge() {
this.age += 1;
}
setAge(age) {
this.age = age;
}
}
const person = new Person("Li", 10);
console.log(person.getAge); // 11
person.setAge(50);
console.log(person.getAge); // 51
Person.sayHello("John"); // John
在使用class声明实例时,不要直接将实例的this作为返回值赋值给其他变量,这样将会得到undefined:
class Animal {
speak() {
return this;
}
static eat() {
return this;
}
}
let obj = new Animal();
console.log(obj.speak()); // Animal {}
let speak = obj.speak;
console.log(speak()); // undefined
配合使用extends可以实现继承,继承是指获得被继承实例的状态和方法,继承前记得在构造函数里super一下哦:
class Animal {
constructor(name) {
this.name = name;
this.state = {value:"Animal"};
}
speak() {
console.log(this.name + ' makes a noise.');
}
jump() {
console.log('Animal jump.');
}
}
class Dog extends Animal {
constructor(name) {
super(name); // call the super class constructor and pass in the name parameter
this.state = {value:"Dog"};
}
// 当具有相同方法函数时,自身方法函数会替代继承实例的方法函数
speak() {
console.log(this.name + ' barks.');
console.log(this.state);
}
}
let d = new Dog('Mitzie');
d.jump(); // 打印 Animal jump.
d.speak(); // 打印 Mitzie barks. 和 打印 {value: "Dog"}
(贴士)无论是渲染、生命周期钩子函数、内部方法,状态都可以被继承。另外,尽量使用组合来代替继承,即通过this.props.children的方式一层层嵌套组件来实现同样效果。
若在class中加上render()方法,便可渲染出标签组件:
import React from 'react';
import './css/color.css';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
clickHandle(e) {
// some code...
}
render() {
return(<div className="red" onClick={this.clickHandle}>www.helloui.net</div>);
}
}
export default App;
模板字符串
模板字符串由两个``表示,它允许嵌入表达式的字符串字面量及使用多行字符串。
当在文本中需要换行时无需加上/n,可直接换行。
console.log(`string text line 1
string text line 2`);
//string text line 1
//string text line 2
用${ }表示对变量的引用:
var a = 5;
var b = 10;
console.log(`Fifteen is ${a + b} and
not ${2 * a + b}.`);
// "Fifteen is 15 and
// not 20."
嵌入式用法,如对相同前缀的样式引用:
var item = {
isCollapsed: true,
checkClass: function() {
return false
}
}
const classes = `the class name is ${ item.checkClass() ? '' : `icon-${item.isCollapsed ? 'expander' : 'collapser'}` }`;
console.log(classes); // 打印 the class name is icon-expander
标记式用法,常用在function定义的函数中,第一个参数表示字符串数组,其他参数表示按顺序排序的字符串表达式:
var person = 'Mike';
var age = 28;
function myTag(strings, personExp, ageExp) {
var str0 = strings[0]; // 字符串 "That "
var str1 = strings[1]; // 字符串 " is a "
var ageStr;
if(ageExp > 99) {
ageStr = 'centenarian';
} else {
ageStr = 'youngster';
}
return `${str0}${personExp}${str1}${ageStr}`;
}
var output = myTag`That ${ person } is a ${ age }`; // 此处无需括号
console.log(output); // That Mike is a youngster
String.raw()用法,表示将所有文本都当成字符处理,包括转义字符:
var str = String.raw`Hi\n${2+3}! `;
console.log(str); // 打印 Hi\n5!
console.log(str.length); // 打印 6
let
let用于声明一个块级范围的变量,不支持重新声明多个名称相同的变量。其声明的变量作用域仅在于块级范围:
let x = 1;
if(x === 1) {
let x = 2;
console.log(x); // 打印: 2
}
console.log(x); // 打印: 1
另外,let声明的变量并不等同默认定义为 win 的一个属性:
var x = 'global';
let y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined,该处在使用webpack打包时便会报出错误
const
const 用于声明一个不可改变的常量。
const CLICK_EVENT = "CLICK_EVENT";
CLICK_EVENT = "CHANDE_EVENT"; // 会报错,无法通过打包编译
但const定义对象时,对象属性可以改变。即const仅保证指针不发生改变,修改对象的属性不会改变对象的指针,所以是被允许的。也就是说const定义的引用类型只要指针不发生改变,其他的改变都是允许的。
const MY_OBJECT = {id:1};
MY_OBJECT.id = 2;
console.log(MY_OBJECT); // 打印 {id: 2}
弄清楚了以上几个es6语法糖,再看react的代码就会轻松很多了。