一、什么是严格模式
JavaScript 除了提供正常模式外,还提供了严格模式(strict mode)。ES5 的严格模式是采用具有限制性
JavaScript变体的一种方式,即在严格的条件下运行 JS 代码。严格模式在 IE10
以上版本的浏览器中才会被支持,旧版本浏览器中会被忽略。
严格模式对正常的 JavaScript 语义做了一些更改:
消除了 Javascript 语法的一些不合理、不严谨之处,减少了一些怪异行为。 消除代码运行的一些不安全之处,保证代码运行的安全。
提高编译器效率,增加运行速度。 禁用了在 ECMAScript 的未来版本中可能会定义的一些语法,为未来新版本的 Javascript
做好铺垫。比如一些保留字如:class,enum,export, extends, import, super 不能做变量名
启用严格模式
// 情况一 :为脚本开启严格模式
<!-- 为整个脚本(script标签)开启严格模式 -->
<script>
'use strict';
// 下面js代码会按照严格模式执行代码
</script>
//情况二: 为函数开启严格模式
function fn(name){
'use strict';
console.log(fn.arguments);
console.log(arguments.callee)//返回当前函数
console.log(fn.caller)//返回当前函数是在那个函数中调用
}
严格模式下:
1.无法意外创建全局变量
2.严格模式会使引起静默失败(silently fail)注意:不报错也没有任何效果)的赋值操作抛出异常;
3.严格模式下试图删除不可删除的属性
4.严格模式不允许函数参数有相同的名称
5.不允许以0开头的八进制语法
6.在严格模式下,不允许使用with语句
8.严格模式下,this绑定不会默认转成对象在严格模式下setTimeout函数内部的this指向:
1.无法意外创建全局变量
'use strict'
function foo() {
age = 20
}
foo()
console.log(age);//这里的age变量在非严格模式下是可以访问到的,在严格模式下访问会报错
2.严格模式会使引起静默失败(silently fail)注意:不报错也没有任何效果)的赋值操作抛出异常;
'use strict'
true.name = "abc"
NaN = 123
3.严格模式下试图删除不可删除的属性
'use strict'
var obj = {};
Object.defineProperty(obj, "name", {
configurable: false,//不可配置
writable: false,//不可重写
value: "why"
})
console.log(obj.name)
obj.name = "kobe"
delete obj.name
4.严格模式不允许函数参数有相同的名称
'use strict'
function foo(x, y, x) {
console.log(x, y, x)
}
foo(10, 20, 30);//函数foo有两个相同名字的形参x,这在严格模式下会报错
5.不允许以0开头的八进制语法
'use strict'
var errorNum=0123;//严格模式下不支持这种写法,可以采用以下的写法代替
var num = 0o123 // 八进制
var num2 = 0x123 // 十六进制
var num3 = 0b100 // 二进制
console.log(errorNum,num, num2, num3)
6.在严格模式下setTimeout函数内部的this指向:
'use strict'
setTimeout(()=> {
console.log(this);//window
}, 1000);
setTimeout(function(){
console.log(this);//window
},1000)
二、ES5
JSON转化
fn()
const array = [
{
name: '张三',
},
{
name: '长伞',
}
]
var jsonStr = JSON.stringify(array)
console.log(jsonStr)
console.log(typeof(jsonStr))
//返回一个js对象
var obj = JSON.parse(jsonStr)
console.log(obj)
function Person(name,age){
this.age = age;
this.name = name;
}
Object.create
var p1 = new Person('zs',18)
var obj = Object.create(null,{
name:{
value:'zs',
writable:true,//默认值是false,是否可设置
configurable:true,//是否可删除
enumerable:true//是否可删除
},
sex:{
}
})
数组扩展方法
Array.prototype.indexOf(value) //得到值在数组的第一个下标
Array.prototype.lastIndexOf(value) //最后一个下标
Array.prototype.forEach(function (item, index) {})
Array.prototype.map(function (item, index) {}) //过滤一个新数组返回加工后的值
Array.prototype.filter(function (item, index) {})//过滤数组返回一个新的子数组,返回值条件为true
Array.prototype.reduce(function (pre, item,index) {//遍历累加返回一个最终结果 回调函数 初始值
pre[item] = index
return pre;
})
var array= ["张珊","网站"]
array.forEach(function (intemperate,index){
console.log(intemperate[index])
})
//forEach() 方法不会返回执行结果。也就是说 forEach()方法会修改原来的数组,但是没有返回值。
//而map()方法得到一个新的数组,这个新数组是map 方法修改数组后返回回来的新的数组。
console.log(array.indexOf("网站"))
console.log(array.indexOf("网"))//没找到输出-1
array.map(function(item,index){//返回新数组
console.log(item[index]);
})
var arr = [2,3,5,6]
var res = arr.reduce(function(pre,item){
return pre + item;
},0)
console.log(res)
三、ES6
1.const let
// console.log(a)
//一次定义后不能改变
//var变量 let
//const常量
const PI = '12122';
const obj ={
name:'za'
}//复杂数据类型,地址没有变化就不会变化
obj.name = 'lx';
2.字符串拼接
let name = 'wuxiaodi';
let res = `
hello
${name}
!
`;
let message = "今天下雨了 ";
// message.trim()//删除字符两边的空白符
// message.trimStart()//去掉收不的空格
// message.trimEnd()//去掉尾部的空格
//message.startsWith()//判断字符串是否是以指定字符串开头
//message.endsWith()//判断字符是否以某个字符结尾
//meaasge.includes()//判断是否包含某个子字符
//console.log(message.padStart(22,"%"))
//console.log(message.padEnd(22,"%"));
3.作用域
<script>
//ES6 局部变量 函数作用域 let块作用域
if (true) {
console.log('let使用')
for (let i = 0; i < 5; i++) {
setTimeout(function () {
console.log(i)
})
}
console.log('var使用')
for (var i = 0; i < 5; i++) {
setTimeout(function () {
console.log(i)
})
}
}
// console.log(a)
</script>
4.解构赋值
let { foo: a, hoo: haha } = { foo: 1, hoo: 2 }
console.log(a)
console.log(haha)
//解构赋值
let { x, y = 10 } = { x: 1}
console.log(x, y)
//练习
let arr = [1,2,3]
let {0:first,[arr.length-1]:last} = arr;
console.log(first,last)
//练习
let arr = [1,2,3]
let {0:first,[arr.length-1]:last} = arr;
console.log(first,last)
//函数传参参数
function fn2({x,y,z}){
console.log(x,y,z)
}
fn2({y:1,x:1,z:9})
//json对象提取
let json = {
name:'lili',
sex:'nv'
}
let {name,sex} = json;console.log(name,sex)
5.箭头函数
函数表达式的简写,不需要通过function关键字创建函数,并且还可以省略return关键字。
箭头函数不会绑定自己的 this,箭头函数中的this会继承当前上下文的this关键字。
箭头函数不能作为构造函数使用
[1, 2, 3].map(x => x + 1); // [2, 3, 4]
6.对象字面量改进
这相当于解构赋值的反向操作,用于重新组织一个Object。
const name = 'wuxiaodi';
const age = 8;
const user = { name, age};
定义对象方法时,还可以省去function关键字
app.model({
reducers: {
add() {} //等同于: add: function() {}
},
effects: {
*addRemote() {} //等同于addRemote: function*(){}
},
});
7.数组操作
运行结果
every语法
array.every(function(currentValue,index,arr), thisValue)
使用
let arr = ["张三","李四","王五"]
let result = arr.every((item,index)=>{
return item =="王五"
})
console.log(result)
//伪数组转化为数组
//Array.from(lis) lis可以是document.getElementsByTagName('li')
//将数字转成数组
//Array.of(1,2)
//arr.copyWithin("从某个下标开始替换","从那个位置开始替换","那个位置开始结束替换")
//arr.fill("填充值",填充开始位置,“结束位置”)
//arr.find(function(item,index){return item==="p"})//返回结果是true时不会进行
//arr.findIndex(function(item,index,array){return typeof item ==="笑笑"})//返回下标
some语法
array.some(function(currentValue,index,arr),thisValue)
some() 方法用于检测数组中的元素是否满足指定条件(函数提供)。
some() 方法会依次执行数组的每个元素:
如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测。
如果没有满足条件的元素,则返回false。
注意: some() 不会对空数组进行检测、 不会改变原始数组。
var ages = [23,44,3]
if (ages.some(age => age < 10)) {
console.log('true')
}
1.some():方法用于检测数组中的元素是否有满足指定条件的,若满足返回true,否则返回false;
2.every():方法用于检测数组中所有元素是否都符合指定条件,若符合返回true,否则返回false;
map和each
1、相同点
1) 都是循环遍历数组中的每一项。
2) 每次执行匿名函数都支持三个参数,参数分别为item(当前每一项),index(索引值),arr(原数组)。
3) 匿名函数中的this都是指向window。
4)只能遍历数组。
2、不同点
1) map()会分配内存空间存储新数组并返回,forEach()不会返回数据。
2) forEach()允许callback更改原始数组的元素,map()返回新的数组,map() 不会对空数组进行检测。
二、forEach和map有相同值的区别
相同处:forEach 和 map都相当于封装好的单层for循环,三个值都相同。
不同处:
1、forEach()方法没有返回值,而map()方法有返回值。
2、forEach遍历通常都是直接引入当前遍历数组的内存地址,生成的数组的值发生变化,当前遍历的数组对应的值也会发生变化。
3、map遍历的后的数组通常都是生成一个新的数组,新的数组的值发生变化,当前遍历的数组值不会变化。
4、总的来说 map 的速度大于forEach。
三、使用场景
forEach适合于你并不打算改变数据的时候。
map()适用于你要改变数据值的时候。不仅仅在于它更快,而且返回一个新的数组。这样的优点在于你可以使用复合(composition)(map(),
filter(), reduce()等组合使用)。
性能上来说for>forEach>map
filter
1、创建新数组
2、不改变原数组
3、输出的是判断为true的数组元素形成的新数组
4、回调函数参数,item(数组元素)、index(序列)、arr(数组本身)
5、使用return操作输出,会循环数组每一项,并在回调函数中操作
示例:
let newArr = arr.filter((item,index)=>{
return item==="王五"
});
console.log(newArr)
常用数组方法
8.Spread Operator
3 个点 …,有几种不同的使用方法
可用于组装数组
const todos = ['Learn dva'];
[...todos, 'Learn antd']; // ['Learn dva', 'Learn antd']
也可用于获取数组的部分项
const arr = ['a', 'b', 'c'];
const [first, ...rest] = arr;
rest; //['b', 'c']
// With ignore
const [first, , ...rest] = arr;
rest; // ['c']
还可收集函数参数为数组
function directions(first, ...rest) {
console.log(rest);
}
directions('a', 'b', 'c'); // ['b', 'c'];
代替apply
const foo = {
a: 1,
b: 2,
};
const bar = {
b: 3,
c: 2,
};
const d = 4;
const ret = { ...foo, ...bar, d }; // { a:1, b:3, c:2, d:4 } PS:如果有相同的key,后面的会覆盖前面的
对于 Object 而言,用于组合成新的 Object 。(ES2017 stage-2 proposal)
function foo(x, y, z){}
const args = [1, 2, 3];
// 下面两句效果相同
foo.apply(null, args);
foo(...args);
9.Math
console.log(Math.pow(3,3))
console.log(Math.pow(30,3))
console.log(30 ** 3)//求一个数的n次方
console.log(30 ** (3 ** 3))
Math.floor()
Math.floor(11.46)=Math.floor(11.68)=Math.floor(11.5)=11
Math.floor(-11.46)=Math.floor(-11.68)=Math.floor(-11.5)=-12
Math.ceil()
英文含义为:天花板,所以是向上取整,它就是天花板函数。会取不小于自变量的最大整数,这样自变量是3.1或3.9,返回都是4;自变量是-2.1或-2.9,返回的都是-2
Math.ceil(11.46)=Math.ceil(11.68)=Math.ceil(11.5)=12
Math.ceil(-11.46)=Math.ceil(-11.68)=Math.ceil(-11.5)=-11
3.Math.round()
英文含义为:周围,环绕,这个就是常用的四舍五入函数。因为它会返回离自变量最近的整数,这个返回的整数可能大于也可能小于原来的数,但是一定是离它最近的那个整数,比如12.5返回13,12.4返回12。
小数点后第一位<5
正数:Math.round(11.46)=11
负数:Math.round(-11.46)=-11
小数点后第一位>5
正数:Math.round(11.68)=12
负数:Math.round(-11.68)=-12
小数点后第一位=5
正数:Math.round(11.5)=12
负数:Math.round(-11.5)=-11
总结:以上逻辑即俗称的“四舍五入”
Math.trunc()
log(Math.trunc(-1.33))//去除小数部分 -1
练习
let {log} = console;
log(Math.floor(1.33))//1
log(Math.ceil(1.33))//2
log(Math.trunc(1.33))//去除小数部分 1
log(Math.floor(-1.33))//-2
log(Math.ceil(-1.33))//-1
log(Math.trunc(-1.33))//去除小数部分 -1
//判断是正数就返回正数判断是负数就返回负数 判断是NAN就返回NAN
log(Math.sign(NaN))
log(Math.sqrt())//平方根
log(Math.cbrt())//立方根
//求所有参数的平方和的平方根
log(Math.hypot(4,9,16))//Math.sqrt(4*4+9*9+16*16)
log(Number.isNaN(0));
Number.isInteger(1);//判断是否是整数isInteger
Number.parseInt(str);//将字符串转化为相应数值
Number.isFinite(0)//判断是否是有限大的数
10.Object
let obj1 = {a:1}
let obj2 = {b:2}
let newObj = Object.assign(obj1,obj2)
console.log(newObj)//Object { a: 1, b: 2 }
11.Set集合
let st = new Set([1,2,3])
console.log(st)
console.log(st.size)
st.add(7)//无法添加相同的元素
st.delete(2);//判断是否删除
st.has(10)//判断是否存在
st.keys()
st.values()
//entries 获取键值对
console.log(st.entries())
// st.forEach((item,index) => console.log(item))
let str = "absdgsd"
console.log([...new Set(str)].join(''))//join() 方法用于把数组中的所有元素放入一个字符串。
12.Map集合
let p2 = {name:'keke'}
let map = new Map([
['a',1],
[p2,2]
])
console.log(map)
运行结果
Map.prototype.clear()
Map.prototype.delete(key)
Map.prototype.entries()
Map.prototype.forEach()
Map.prototype.get(key)
Map.prototype.has(key)
Map.prototype.keys()
Map.prototype.set(key, value)
Map.prototype.values()
for in
举例
Promise
let promise = new Promise(function(resolve,reject){
setTimeout(()=>{
console.log("成功")
resolve();
},1000)
})
async function Fn(){
console.log("返回")
await new Promise((resolve,reject)=>{
setTimeout(() =>{
console.log("返回1")
resolve();
},4000)
})//等待第一个执行成功继续执行下一步,与消耗时间无关
await new Promise((resolve,reject)=>{
setTimeout(() =>{
console.log("返回2")
},1000)
})
} Fn()
console.log(promise.resolve())
console.log(promise.reject())
console.log(promise.catch())
console.log(promise.finally())
console.log(promise.all())//一般同时执行多个回调
构造函数
js
function Person(name='array', age) {
this.name = name
this.age = age
// this.say = function () {
// console.log('hello')
// }
}
//如果每次都创建一个实例对象,非常占用内存
//所以将方法挂到原型上
Person.prototype.say = function () {
console.log(`我挣钱很多,我是${this.name}`)
}
let p1 = new Person('sd',11)
p1.say()
ES6
//ES6
class Person{
constructor(name,age){
this.name = name;
this.age = age;
}
sayhi(){
console.log(`你好我是${this.name}`)
}
}
let pa1 = new Person('zhang',00)
pa1.sayhi()
复用
class Person{
constructor(name,age){
this.name = name;
this.age = age;
}
sayhi(){
console.log(`你好我是${this.name}`)
}
}
let pa1 = new Person('zhang',00)
pa1.sayhi();
class Student extends Person{
constructor(name,age,score){
super(name,age);
this.score = score;
}
}