js 基础
js 基础
ES5 和 ES6 的区别
系统库的引入
Es5:需要先使用 require 导入 React 包,成为对象,再去进行真正引用
Es6:可以使用 import 方法来直接实现系统库引用,不需要额外制作一个类库对象
在ES5里,如果使用CommonJS标准,引入React包基本require进行
ES5
var React = require("react");
var {
Component,
PropTypes
} = React; //引用React抽象组件
var ReactNative = require("react-native");
var {
Image,
Text,
} = ReactNative; //引用具体的React Native组件
在ES6里,import写法更为标准
ES6
import React, {
Component,
PropTypes,
} from 'react';
import {
Image,
Text
} from 'react-native'
导出及引用单个类
Es5:要导出一个类给别的模块用,一般通过 module.exports 来实现。引用时,则依然通过 require 方法来获取
Es6:可以使用 export default 来实现相同的功能,使用 import 方法来实现导入
导出
在ES5里,要导出一个类给别的模块用,一般通过module.exports来导出
ES5
var MyComponent = React.createClass({});
module.exports = MyComponent;
在ES6里,通常用export default来实现相同的功能:
ES6
export default class MyComponent extends Component {}
引用
ES5
var MyComponent = require('./MyComponent');
ES6
import MyComponent from './MyComponent';
定义组件
Es5:组件类的定义通过 React.createClass 实现
Es6:组件类继承 React.Component 类
在ES5里,通常通过React.createClass来定义一个组件类
ES5
var Photo = React.createClass({
render: function () {
return (
<Image source={this.props.source} />
);
},
});
在ES6里,我们通过定义一个继承自React.Component的class来定义一个组件类
ES6
class Photo extends React.Component {
render() {
return (
<Image source={this.props.source} />
);
}
}
组件内部定义方法
Es5:采用的是 ###:function()的形式,方法大括号末尾需要添加逗号
Es6:省略了【: function】这一段,并且结尾不需要加逗号来实现分隔
ES5
var Photo = React.createClass({
componentWillMount: function () {
},
render: function () {
return (
<Image source={this.props.source} />
);
},
});
ES6
class Photo extends React.Component {
componentWillMount() {
}
render() {
return (
<Image source={this.props.source} />
);
}
}
定义组件的属性类型和默认属性
Es5:属性类型和默认属性分别通过 propTypes 和 getDefaultProps 方法来实现
Es6:统一使用 static 来实现
在ES5里,属性类型和默认属性分别通过propTypes和getDefaultProps方法来实现
ES5
var Video = React.createClass({
getDefaultProps: function () {
return {
autoPlay: false,
maxLoops: 10,
};
},
propTypes: {
autoPlay: React.PropTypes.bool.isRequired,
maxLoops: React.PropTypes.number.isRequired,
posterFrameSrc: React.PropTypes.string.isRequired,
videoSrc: React.PropTypes.string.isRequired,
},
render: function () {
return (
<View />
);
},
});
在ES6里,可以统一使用static来实现
ES6
class Video extends React.Component {
static defaultProps = {
autoPlay: false,
maxLoops: 10,
}; 注意这里有分号
static propTypes = {
autoPlay: React.PropTypes.bool.isRequired,
maxLoops: React.PropTypes.number.isRequired,
posterFrameSrc: React.PropTypes.string.isRequired,
videoSrc: React.PropTypes.string.isRequired,
}; 注意这里有分号
render() {
return (
<View />
);
} 注意这里既没有分号也没有逗号
}
初始化 STATE
Es5:初始化 state 的方法是固定的 getInitialState
Es6:第一种,直接构造 state 函数;第二种,相当于 OC 中的方法重写,重写 constructor 方法
ES5
var Video = React.createClass({
getInitialState: function () {
return {
loopsRemaining: this.props.maxLoops,
};
},
})
ES6
第一种
class Video extends React.Component {
state = {
loopsRemaining: this.props.maxLoops,
}
}
第二种
class Video extends React.Component {
constructor(props) {
super(props);
this.state = {
loopsRemaining: this.props.maxLoops,
};
}
}
ES5 常用方法
indexOf
返回某个指定的字符串值在字符串中首次出现的位置
/**
* string.indexOf(searchvalue,fromindex) 。
* searchvalue 必需。规定需检索的字符串值。
* fromindex 可选的整数参数。规定在字符串中开始检索的位置。它的合法取值是 0 到 stringObject.length - 1。如省略该参数,则将从字符串的首字符开始检索。
*/
var str = "Hello world!";
console.log(str.indexOf("Hello") + "<br />");
forEach
方法用于调用数组的每个元素,并将元素传递给回调函数
注意:
不会对空数组进行检测
/*array.forEach(function(currentValue,index,arr){},thisValue)
* 参数1:函数,必须
* 1)当前元素(必须)
* 2)当前元素的索引值(可选)
* 3)当前元素所属的数组对象(可选)
*
* 参数2:可选,传递给函数的值,一般用“this”的值,如果参数为空,undefined传递给this值
* */
let myArr = [0, 1, 2, 3];
myArr.forEach(function (item, index, arr) {
console.log("item:" + item); //1
console.log(this); //{sex: "女"}
}, obj);
map
遍历所有元素,将所有元素给一个函数处理,处理后的新元素组成一个新数组返回
map 方法会按照原始数组元素顺序依次处理元素
注意:
1.不会对空数组进行检测
2.不会改变原始数组
* array.map(参数1,参数2)
* 参数1:函数 (必须)
* 函数可传三个参数 :
* 1)当前元素的值(必须)
* 2)当前元素的索引值 index(可选)
* 3) 当前元素属于的数组对象(可选)
* 参数2 :可选,做为执行函数回调的时候使用,传递给函数,用作this 的值*/
let num = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let cs = { a: "ceshi" };
num.map(function (item, index, num) {
console.log("item:" + item); //1数组第几位下标的内容
console.log("index:" + index); //0,数组的下标
console.log("num:" + num); //1,2,3,4,5,6,7,8,9
console.log(this);
},cs);
filter
将数组中所有满足条件的元素组成一个新数组返回
注意:
1.不会对空数组进行检测
2.不会改变原始数组
/**
* array.filter(参数1,参数2,参数3)
* 参数1 当前元素的值(必须)
* 参数2 当前元素的索引值(可选)
* 参数3 当前元素属于的数组对象(可选)
* **/
let data = [0, 1, 2, 3];
let arrayFilter = data.filter(function (item) {
return item > 0;
});
console.log(arrayFilter); //[1, 2, 3]
some
用于检测数组中的元素是否满足指定条件
依次执行数组的每个元素:
如果有一个元素满足条件,则表达式返回 true , 剩余的元素不会再执行检测
如果没有满足条件的元素,则返回 false
注意:
1.不会对空数组进行检测
2.不会改变原始数组
var obj = {
a: "qq",
};
var arr = [11, 22, 33, 44, 55];
var result1 = arr.some(function (item, index, arr) {
console.log(item, index, arr, this);
console.log("this", this);
return item > 22;
}, obj);
console.log(result1);
every
用于检测数组所有元素是否都符合指定条件
依次执行数组的每个元素:
如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测
如果所有元素都满足条件,则返回 true
注意:
1.不会对空数组进行检测
2.不会改变原始数组
var obj = {
a: "qq",
};
var arr = [11, 22, 33, 44, 55];
var result2 = arr.every(function (item, index, arr) {
console.log(item, index, arr, this);
return item > 22;
}, obj);
console.log(result2);
ES6 常用方法
let 变量声明
1.不存在变量提升
console.log(b1); // 报错:es6.html:19 Uncaught ReferenceError: Cannot access 'b1' before initialization ===> 不能在初始化之前访问'b1'
let b1 = 10;
2.块作用域
if (1) {
var a1 = 100;
let b2 = 10;
}
console.log(a1); // 100
console.log(b2) // 报错:b2 is not defined ===> b2没有定义
3.同一作用域下不能声明同名变量
let a2 = 100;
let a2 = 10;
console.log(a2)
// 控制台报错:Identifier 'a2' has already been declared ===> 标识符'a2'已经声明
const 变量声明
1.一旦声明必须赋值,不能使用 null 占位
const ceshi
//Uncaught SyntaxError: Missing initializer in const declaration 未捕获的SyntaxError: const声明中缺少初始化式
2.声明后不能再修改
const ceshi1 = 100;
ceshi1 = 200;
console.log(ceshi1) //Uncaught TypeError: Assignment to constant variable. 常数变量赋值
3.如果声明的是复合类型数据,可以修改其属性
const list = [];
list[0] = 10;
console.log(list); // [10]
const obj = { a: 100 };
obj.name = 'apple';
obj.a = 10000;
console.log(obj); // {a:10000,name:'apple'}
解构赋值
1.数组
let [a, b, c] = [1, 2, 3];//从数组中提取值,按照对应的位置,对变量赋值
console.log(a);//1
console.log(b);//2
console.log(c);//3
2.字符串
const [a11, b11, c11, d11, e11] = "hello";
console.log(a11);//h
console.log(b11);//e
console.log(c11);//l
console.log(d11);//l
console.log(e11);//o
3.对象
let { foo9: foo91, bar22: bar2 } = { foo9: 'aaa', bar22: "bbb" };
console.log(foo91);//aaa
console.log(bar2);//bbb
模板字符串
let cs = 'Hello World'
console.log(`foo ${cs} bar`);//foo Hello World bar
function fn() {
return "Hello World"
}
console.log(`foo ${fn()} bar`);//foo Hello World bar
箭头函数
定义用的就是一个箭头, 箭头函数相当于匿名函数,并且简化了函数定义。
1.箭头函数看上去是匿名函数的一种简写,但实际上,箭头函数和匿名函数有个明显的区别:箭头函数内部的 this 是词法作用域,由上下文确定。
this 总是指向词法作用域,也就是外层调用者 obj
var obj = {
birth: 1990,
getAge: function () {
var b = this.birth; // 1990
var fn = () => new Date().getFullYear() - this.birth; // this指向obj对象
return fn();
},
};
console.log(obj.getAge());
2.this 在箭头函数中已经按照词法作用域绑定了,所以,用 call()或者 apply()调用箭头函数时,无法对 this 进行绑定,即传入的第一个参数被忽略:
var obj2 = {
birth: 1990,
getAge: function (year) {
var b = this.birth; // 1990
var fn = (y) => y - this.birth // this.birth仍是1990
return fn.call({ birth: 2000 }, year);
}
};
console.log(obj2.getAge(2015));
扩展运算符
可以将一个数组转为逗号分隔的参数序列
1.赋值结构
let [head, ...tail] = [1, 2, 3, 4];
console.log(head);//1
console.log(tail);//[2,3,4]
2.push
let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];
arr1.push(...arr2);
console.log(arr1);// [0, 1, 2, 3, 4, 5]
3.使用扩展运算符复制数组,复制后 a3 的内容不变
let a3 = [1, 2, 3, 4];
let a4 = [...a3];
console.log(a4);//[1,2,3,4]
a4 = [9]
console.log(a4);//[9]
console.log(a3);//[1,2,3,4]
4.es6 扩展运算符合并数组
const arr3 = ["a", "b"];
const arr4 = ["c"];
const arr5 = ["d", "e"];
console.log([...arr3, ...arr4, ...arr5]);//["a", "b", "c", "d", "e"]
闭包
闭包概念
闭包:有权访问另一个函数作用域中的变量的函数;一般情况就是在一个函数中包含另一个函数。
function person() {
var name = "有鱼";
function cat() {
console.log(name);
}
return cat;
}
var per = person(); // per的值就是return后的结果,即cat函数
per(); // 有鱼 per()就相当于cat(),而且变量name没有销毁,一直存在内存中,供函数cat调用
闭包原理
闭包的实现原理,其实是利用了作用域链的特性,我们都知道作用域链就是在当前执行环境下访问某个变量时,如果不存在就一直向外层寻找,最终寻找到最外层也就是全局作用域,这样就形成了一个链条。
闭包优缺点
优点
1.隐藏变量,避免全局污染
2.可以读取函数内部的变量
缺点
1.导致变量不会被垃圾回收机制回收,造成内存消耗
2.不恰当的使用闭包可能会造成内存泄漏的问题
案例
var a = 10;
function Add3(){
var a = 10;
return function(){
a++;
return a;
};
};
var cc = Add3();
console.log(cc());
console.log(cc());
console.log(cc());
console.log(a);
promise
Promise 是一个构造函数,用来传递异步操作的消息,链式调用,避免层层嵌套的回调函数。
Promise 对象有三个状态:
1.进行中(pending)
2.成功(resolved)
3.失败(rejected)
创建 promise
let promise = new Promise((resolve, reject) => {
resolve("成功") / reject("失败");
});
调用 promise
当调用 resolve()回调执行的是.then(res=>{})。当调用 reject()回调执行的是.catch(error=>{})。
promise
.then((res) => {
console.log(res); //成功
})
.catch((error) => {
console.log(error);//失败
});
链式调用
创建
function promise1(status) {
return new Promise((resolve, reject) => {
if (status) {
resolve("参数");
console.log("promise1成功");
} else {
reject("参数");
console.log("promise1失败");
}
});
}
function promise2(status) {
return new Promise((resolve, reject) => {
if (status) {
resolve("参数");
console.log("promise2成功");
} else {
reject("参数");
console.log("promise2失败");
}
});
}
调用
promise1(1)
.then((res) => {
// 调用promise1
console.log(res);
return promise2(0);
})
.then((res) => {
// 调用promise2,return就可以打印第二个参数
console.log(res);
})
.catch((error) => {});
all
数组内有 promise 必须全部执行成功,才会执行 then 回调,只要有一个不成功就会执行 catch
Promise.all([promise1(1), promise2(1)])
.then((res) => {
console.log("全部调用成功");
})
.catch((error) => {
console.log("失败");
});
race
当第一个 promise 返回 reject,那么所有的就失败;如果有一个返回 reject,就代表成功
Promise.race([promise1(1), promise2(1)])
.then((res) => {
console.log("成功");
})
.catch((error) => {
console.log("失败");
});
Promise 优缺点
优点:
1.解决回调
2.链式调用
3.减少嵌套
缺点:
1.无法监测进行状态
2.新建立即执行且无法取消
3.内部错误无法抛出