JavaScript 除了提供正常模式外,还提供了严格模式(strict mode)。ES5 的严格模式是采用具有限制性
JavaScript变体的一种方式,即在严格的条件下运行 JS 代码。严格模式在 IE10
以上版本的浏览器中才会被支持,旧版本浏览器中会被忽略。
严格模式对正常的 JavaScript 语义做了一些更改:
消除了 Javascript 语法的一些不合理、不严谨之处,减少了一些怪异行为。 消除代码运行的一些不安全之处,保证代码运行的安全。
提高编译器效率,增加运行速度。 禁用了在 ECMAScript 的未来版本中可能会定义的一些语法,为未来新版本的 Javascript
做好铺垫。比如一些保留字如:class,enum,export, extends, import, super 不能做变量名
启用严格模式
// 情况一 :为脚本开启严格模式
//情况二: 为函数开启严格模式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)
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) {})//过滤数组返回一个新的子数组,返回值条件为trueArray.prototype.reduce(function (pre, item,index) {//遍历累加返回一个最终结果 回调函数 初始值 pre[item] = indexreturn pre;})
var array= ["张珊","网站"]array.forEach(function (intemperate,index){console.log(intemperate[index])})//forEach() 方法不会返回执行结果。也就是说 forEach()方法会修改原来的数组,但是没有返回值。//而map()方法得到一个新的数组,这个新数组是map 方法修改数组后返回回来的新的数组。console.log(array.indexOf("网站"))console.log(array.indexOf("网"))//没找到输出-1array.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)
// console.log(a)//一次定义后不能改变//var变量 let//const常量const PI = '12122';const obj ={name:'za'}//复杂数据类型,地址没有变化就不会变化obj.name = 'lx';
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,"%"));
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)
函数表达式的简写,不需要通过function关键字创建函数,并且还可以省略return关键字。
箭头函数不会绑定自己的 this,箭头函数中的this会继承当前上下文的this关键字。
箭头函数不能作为构造函数使用
[1, 2, 3].map(x => x + 1); // [2, 3, 4]
这相当于解构赋值的反向操作,用于重新组织一个Object。
const name = 'wuxiaodi';
const age = 8;
const user = { name, age};
定义对象方法时,还可以省去function关键字
app.model({reducers: {add() {} //等同于: add: function() {}},effects: {*addRemote() {} //等同于addRemote: function*(){}},
});
运行结果
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 ==="笑笑"})//返回下标
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;
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
1、创建新数组
2、不改变原数组
3、输出的是判断为true的数组元素形成的新数组
4、回调函数参数,item(数组元素)、index(序列)、arr(数组本身)
5、使用return操作输出,会循环数组每一项,并在回调函数中操作
示例:
let newArr = arr.filter((item,index)=>{return item==="王五"});console.log(newArr)
常用数组方法
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);
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))//1log(Math.ceil(1.33))//2log(Math.trunc(1.33))//去除小数部分 1log(Math.floor(-1.33))//-2log(Math.ceil(-1.33))//-1log(Math.trunc(-1.33))//去除小数部分 -1
//判断是正数就返回正数判断是负数就返回负数 判断是NAN就返回NANlog(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);//判断是否是整数isIntegerNumber.parseInt(str);//将字符串转化为相应数值Number.isFinite(0)//判断是否是有限大的数
let obj1 = {a:1}let obj2 = {b:2}let newObj = Object.assign(obj1,obj2)console.log(newObj)//Object { a: 1, b: 2 }
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() 方法用于把数组中的所有元素放入一个字符串。
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 = namethis.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
//ES6class 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;}}