ES5~11
来源:尚硅谷公开课视频
目录
- ES5
- 严格模式
- JSON对象
- Object(对象)扩展
- Object.create
- Object.defineProperties
- 对象本身的两个方法
- Array(数组)扩展
- Function(函数)扩展
- ES6
- let & const 关键字
- 解构赋值
- 模板字符串
- 对象的简写方式
- 箭头函数
- 形参默认值
- rest参数
- 扩展运算符
- Promise对象
- Symbol属性
- iterator接口机制
- Generator函数
- Class类
- 字符串方法扩展
- 数值方法扩展
- 数组方法扩展
- 对象方法扩展
- 深度克隆
- Set 容器
- Map 容器
- for of 遍历
- ES7
- ** & includes
- ES8
- async & await
- 对象方法的扩展
- ES9
- rest参数 & 扩展运算符
- 正则扩展
- 在这里插入图片描述
- ES10
- 对象方法扩展 Object.fromEntries
- 字符串方法扩展 trimStart & trimEnd
- 数组方法扩展 flat & flatMap
- Symbol.prototype.description
- ES11
- 私有属性
- Promise.allSettled
- String.prototype.matchAll
- 可选链操作符
- 动态import
- BigInt
- globalThis
ES5
严格模式
1. 理解:* 除了正常运行模式(混杂模式),ES5添加了第二种运行模式:"严格模式"(strict mode)。* 顾名思义,这种模式使得Javascript在更严格的语法条件下运行
2. 目的/作用* 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为* 消除代码运行的一些不安全之处,为代码的安全运行保驾护航* 为未来新版本的Javascript做好铺垫
3. 使用* 在全局或函数的第一条语句定义为: 'use strict';* 如果浏览器不支持, 只解析为一条简单的语句, 没有任何副作用
4. 语法和行为改变* 必须用var声明变量* 禁止自定义的函数中的this指向window* 创建eval作用域* 对象不能有重名的属性* 函数不能有重名的形参
JSON对象
1. JSON.stringify(obj/arr)* js对象(数组)转换为json对象(数组)
2. JSON.parse(json)* json对象(数组)转换为js对象(数组)严格来说,只有JSON对象和JSON数组,没有“JSON字符串”这一概念。
JSON是数据传输的格式。如果服务器发送给我们的是普通的字符串,我们并不能直接使用,因为服务器发送的很可能是一长串数据,里面包含了多个数据,无法对数据进行分类。因此我们需要的是JSON的对象和数组可以与原生的对象和数组进行转化,即,一一对应的关系。[对象(数组)都是用来保存数据的。]
<script type="text/javascript">var obj = {name : 'kobe',age : 39};obj = JSON.stringify(obj);console.log( typeof obj); // stringobj = JSON.parse(obj);console.log(obj); // object</script>
Object(对象)扩展
ES5给Object扩展了一些静态方法, 常用的2个:
Object.create 和 Object.defineProperties
Object.create
Object.create(prototype, [descriptors]) (prototype是指定的原型,[descriptors]是相应的描述)* 作用: 以指定对象为原型创建新的对象* 为新的对象指定新的属性, 并对属性进行描述value: 指定值writable: 标识当前属性值是否是可修改的, 默认为falseconfigurable: 标识当前属性是否可以被删除 默认为falseenumerable: 标识当前属性是否能用for in 枚举 默认为false
先看以下代码
<script type="text/javascript">var obj = {username: 'damu' , age: 30}var obj1 = {};obj1 = Object.create(obj);console.log(obj1);</script>
此时结果如下图所示:
此时,指定obj为原型,age和username是原型上的2个属性,因此是可继承的。
如果没有obj1 = Object.create(obj);
则_proto_
中没有这两个属性,结果如下图所示:
当然,Object.create的作用不止如此。
<script type="text/javascript">var obj = {username: 'damu' , age: 30}var obj1 = {};obj1 = Object.create(obj , {sex: {value: '男'}});console.log(obj1);</script>
结果如下图所示:
此时,不仅指定了原型,而且给当前的对象(obj1)扩展了属性。如果console.log(obj1.sex);
则可以返回结果男
。
<script type="text/javascript">var obj = {username: 'damu' , age: 30}var obj1 = {};obj1 = Object.create(obj , {sex: {value: '男',
// writable: true,
// configurable: true
// enumerable: true}});console.log(obj1);console.log(obj1.sex); // 男obj1.sex = '女'; // 修改失败,需要指定 writable: trueconsole.log(obj1.sex); // 男delete obj1.sex; // 删除失败,需要指定 configurable: trueconsole.log(obj1);for(var i in obj1){ /* 枚举obj1中的属性 */console.log(i); // username,age 枚举sex属性失败,需要指定enumerable: true}</script>
Object.defineProperties
Object.defineProperties(object, descriptors) object为指定的对象,descriptors为扩展的属性* 作用: 为指定对象定义扩展多个属性* get: 用来获取当前属性值得回调函数* set: 监听(修改)当前属性值得触发的回调函数,并且实参即为修改后的值* 存取器属性:setter 用来存值 , getter 用来取值
<script type="text/javascript">var obj2 = {firstName: 'kobe' , lastName: 'bryant'};Object.defineProperties(obj2 , {fullName: {//方法实际上是指定的对象去调用,这里是obj2get: function () {return this.firstName + ' ' + this.lastName;}}})console.log(obj2);</script>
结果如下图所示:
<script type="text/javascript">var obj2 = {firstName: 'kobe' , lastName: 'bryant'};Object.defineProperties(obj2 , {fullName: { // 方法实际上是指定的对象去调用,这里是obj2get: function () { // 获取扩展属性的值,获取扩展属性值时get方法自动调用return this.firstName + ' ' + this.lastName;},set: function (data) { // 监听(修改)扩展属性,当扩展属性发生变化时会自动调用,自动调用后会将变化的值作为实参注入到set函数;这里的data为'tim duncan'。console.log('set()' , data); // set() tim duncan/* 修改不了扩展属性(fullName)的值,但能去修改原来属性(firstName和lastName)的值(原来属性的值已经被修改) */var names = data.split(' ');//将'tim duncan'拆分为数组/* 方法实际上是指定的对象去调用,这里是obj2,因此this是obj2 *//* 从原来的属性(firstName和lastName)中获取相应的值 */this.firstName = names[0]; // tim;this.lastName = names[1]; // duncan;}}})/* 当没有以下代码时,不会自动调用get/set方法 */console.log(obj2.fullName); // 获取扩展属性值,自动调用get方法 ;结果为:kobe bryantobj2.fullName = 'tim duncan'; // 监听扩展属性值,自动调用set方法;fullName是扩展属性,无法进行修改。// 但这一句代码是不可缺少的,因为这一句代码的存在才会调用set函数修改firstName和lastName的值。// 因此,这一句代码的实际作用并非修改fullName,而是传入参数'tim duncan'。console.log(obj2.fullName); // 再次获取扩展属性值,再次自动调用get方法;结果为:tim duncan
</script>
对象本身的两个方法
对象本身的两个方法
* get propertyName(){} 用来得到当前属性值的回调函数
* set propertyName(){} 用来监视当前属性值变化的回调函数
原理与上述的Object.defineProperties是相同的。
<script type='text/javascript'>var obj = {firstName : 'kobe',lastName : 'bryant',/* fullName是根据已有的值动态计算出来的 */get fullName(){return this.firstName + ' ' + this.lastName},set fullName(data){var names = data.split(' ');this.firstName = names[0];this.lastName = names[1];}};console.log(obj.fullName); // kobe bryantobj.fullName = 'curry stephen';console.log(obj.fullName); // curry stephen</script>
Array(数组)扩展
1. Array.prototype.indexOf(value) 得到值在数组中的第一个下标
2. Array.prototype.lastIndexOf(value) 得到值在数组中的最后一个下标
3. Array.prototype.forEach(function(item, index){}) 遍历数组
4. Array.prototype.map(function(item, index){}) 遍历数组返回一个新的数组,返回加工之后的值
5. Array.prototype.filter(function(item, index){}) 遍历过滤出一个新的子数组,返回条件为true的值
<script type="text/javascript">/*需求:1. 输出第一个6的下标2. 输出最后一个6的下标3. 输出所有元素的值和下标4. 根据arr产生一个新数组,要求每个元素都比原来大105. 根据arr产生一个新数组, 返回的每个元素要大于4*/var arr = [1, 4, 6, 2, 5, 6];console.log(arr.indexOf(6)); // 2// Array.prototype.lastIndexOf(value) 得到值在数组中的最后一个下标console.log(arr.lastIndexOf(6)); // 5// Array.prototype.forEach(function(item, index){}) 遍历数组arr.forEach(function (item, index) {console.log(item, index); // 1 0,4 1,6 2,2 3,5 4,6 5});// Array.prototype.map(function(item, index){}) 遍历数组返回一个新的数组,返回加工之后的值var arr1 = arr.map(function (item, index) {return item + 10});console.log(arr, arr1); // 1,4,6,2,5,6 11,14,16,12,15,16// Array.prototype.filter(function(item, index){}) 遍历过滤出一个新的子数组, 返回条件为true的值var arr2 = arr.filter(function (item, index) {return item > 4});console.log(arr, arr2); // 1,4,6,2,5,6 6 5 6</script>
Function(函数)扩展
1. Function.prototype.bind(obj) :* 作用: 将函数内的this绑定为obj, 并将函数返回
2. 面试题: 区别bind()与call()和apply()?* 都能指定函数中的this* call()/apply()是立即调用函数* bind()是将函数返回
<script type="text/javascript">var obj = {username: 'kobe'};function foo() {console.log(this);}foo(); // Windowfoo.call(obj); // {username: "kobe"}foo.apply(obj); // {username: "kobe"}/* 可知,在不传参(foo的参数)的情况下,call和apply的使用方式是一样的 */</script>
<script type="text/javascript">var obj = {username: 'kobe'};function foo() {console.log(this);}foo();/* call 直接从第二个参数开始,依次传入参数 */foo.call(obj , 33); // {username: "kobe"} 33foo.apply(obj); // {username: "kobe"} undefinedfoo.apply(obj , 33); // 报错/* apply 第二参数必须是数组,传入的参数放在数组中 */foo.apply(obj , [33]); // {username: "kobe"} 33/* bind 绑定完this不会立即调用当前的函数,而是将函数返回 */foo.bind(obj); // 无输出,本质原因是foo函数未调用var bar = foo.bind(obj);console.log(bar); // 将foo函数输出bar(); // {username: "kobe"} undefinedfoo.bind(obj)(); // 或者不需要用var定义,直接调用; 结果为:{username: "kobe"} undefined/* bind 传参的方法同call一样 */foo.bind(obj , 33)(); // {username: "kobe"} 33/* 回调函数:我们自己定义的函数,但是由系统调用 *//* bind通常指定回调函数的this,示例如下 */setTimeout(function () {console.log(this); // {username: "kobe"} }.bind(obj), 1000) // bind将this由window改为obj
</script>
ES6
let & const 关键字
let
let
1. 作用:* 与var类似, 用于声明一个变量
2. 特点:* 在块作用域内有效,但不影响作用域链,而var是在全局范围内有效* 不能重复声明,而var可以声明多次* 不会预处理, 不存在变量提升;而var存在变量提升(先使用,后定义)
3. 应用:* 循环遍历加监听* 使用let取代var是趋势
<script type="text/javascript">console.log(username); //报错,不存在变量提升let username = 'kobe'; //与var类似, 用于声明一个变量let username = 'wake'; //重复声明,报错let btns = document.getElementsByTagName('button');//有三个按钮for(var i = 0;i<btns.length;i++){btns[i].onclick = function () {alert(i); //每个按钮的结果都是3// var在全局范围内有效,所以全局中只有一个变量i,每次循环时,定时器里面的i指的是全局变量i }}// for循环计数器很适合用let。let有块作用域,每遍历一次时i都是一个版块的,所以在使用i时都是当前块作用域中自己的数据for (var i = 0; i < 10; i++) {setTimeout(function(){console.log(i); // 输出十个 10})}for (let j = 0; j < 10; j++) {setTimeout(function(){console.log(j); // 输出 0123456789})}{ // 不影响作用域链let a = 'aaa';function fn() {console.log(a);}fn(); // 结果为:aaa}
</script>
const
1. 作用:* 定义一个常量(只读)
2. 特点:* 不能修改,声明后必须初始化* 其它特点同let
3. 应用:* 保存不用改变的数据
4. 应用:* 块级作用域
5. 数据和对象* 对于数组和对象的元素修改,不算作对常量的修改,不会报错
6. 注:* const 其实保证的不是变量的值不变,而是保证变量指向的内存地址所保存的数据不允许改动。* 对于简单类型(数值 number、字符串 string 、布尔值 boolean),值就保存在变量指向的那个内存地址,因此 const 声明的简单类型变量等同于常量。而复杂类型(对象 object,数组 array,函数 function),变量指向的内存地址其实是保存了一个指向实际数据的指针,所以 const 只能保证指针是固定的,至于指针指向的数据结构变不变就无法控制了,所以使用 const 声明复杂类型对象时要慎重。
<script type="text/javascript">const sex = '男';console.log(sex);//sex = '女';//不能修改console.log(sex);// 暂时性死区// ES6 明确规定,代码块内如果存在 let 或者 const,代码块会对这些命令声明的变量从块的开始就形成一个封闭作用域。代码块内,在声明变量 PI 之前使用它会报错。var PI = "a";if(true){console.log(PI); // ReferenceError: PI is not definedconst PI = "3.1415926";}{// const 具有块级作用域const a = 'aaa';}console.log(a) // 报错:a is not definedconst TEAM = ['a', 'b', 'c'];TEAM.push('d'); // 不会报错TEAM = 100; // 报错
</script>
解构赋值
1. 理解:* 从对象或数组中提取数据, 并赋值给变量(多个)(解构赋值的通俗理解:解析其结构,解析完以后知道内部的数据,然后再进行赋值)
2. 数组的解构赋值基本let [a, b] = [1, 'atguigu'];可嵌套let [a, [[b], c]] = [1, [[2], 3]];可忽略let [a, , b] = [1, 2, 3];不完全解构let [a = 1, b] = []; // a = 1, b = undefined剩余运算符let [a, ...b] = [1, 2, 3]; // a = 1;b = [2, 3]字符串等let [a, b, c, d, e] = 'hello'; // a='h';b='e';...默认值:let [a = 3, b = a] = []; // a = 3, b = 3let [a = 3, b = a] = [1]; // a = 1, b = 1let [a = 3, b = a] = [1, 2]; // a = 1, b = 2
3. 对象的解构赋值基本let {n, a} = {n:'tom', a:12}let { baz : foo } = { baz : 'ddd' } // foo = 'ddd'可嵌套可忽略let obj = {p: ['hello', {y: 'world'}] };let {p: [x, { y }] } = obj;// x = 'hello'// y = 'world'let obj = {p: ['hello', {y: 'world'}] };let {p: [x, { }] } = obj;// x = 'hello'不完全解构let obj = {p: [{y: 'world'}] };let {p: [{ y }, x ] } = obj;// x = undefined// y = 'world'剩余运算符let {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40};// a = 10// b = 20// rest = {c: 30, d: 40}解构默认值let {a = 10, b = 5} = {a: 3}; // a = 3; b = 5;let {a: aa = 10, b: bb = 5} = {a: 3}; // aa = 3; bb = 5;
4. 用途* 给多个形参赋值
<script type="text/javascript">let obj = {username: 'kobe' , age: 39};/* 通常写法 */let username = obj.username;let age = obj.age;/* 对象的解构赋值* obj是要解构的目标对象,定义两个变量username、age向obj要数据,* 解构的obj是对象,只能以对象的形式来接受数据,而在对象中可以放置属性,* 首先,在等号左边定义的属性username、age是相当于在全局定义的变量,与上述的let方式定义是相同的,* 在解构赋值的时候,等号左边必须是等号右边的对象已有的属性,否则返回undefined,* 并不需要将等号右边的对象所有属性都写上,想要什么属性就写什么属性即可*/let {username , age} = obj; // 解构赋值/* 数组的解构赋值* 等号右边是数组,想要结构的对象是数组,* 因此,等号左边也必须用数组的形式来接受数据* 对象用key值一一对应,数组则用下标一一对应,* 默认是从下标0开始一一对应,也可以直接使用","取得其他的下标*/let arr = [1, 3 , 5 , 'abc' , true];let [] = arr;console.log(a , b , c , d , e);//结果为:1 , 3 , 5 , abc , trueconsole.log(a , b);//结果为:1 , 3console.log(,, a , b);//结果为:5 , abcconsole.log(,,, a , b);//结果为:abc , truefunction foo(obj) {console.log(obj.username , obj.age);}foo(obj);//结果为:kobe 39/*给多个形参赋值* 用{username , age}代替obj* 前提是知道传入的对象obj中有username、age,*/function foo({username , age}) {//相当于在函数内部声明了username、age,与对象的解构赋值在全局声明一样console.log(username , age);//直接使用}foo(obj);//结果为:kobe 39
</script>
模板字符串
模板字符串 : 简化字符串的拼接* 模板字符串必须用 `` 包含* 变化的部分使用 ${xxx} 定义* 内容中可以直接出现换行符
<script type="text/javascript">let obj = {name : 'anverson',age : 41};let a = `我叫:${obj.name}, 我的年龄是:${obj.age}`;let b = `<ul><li>啊</li><li>呀</li></ul>`;
</script>
对象的简写方式
简化的对象写法
* 省略同名的属性值
* 省略方法的function
* 例如:let x = 1;let y = 2;let point = {x,y,setX (x) {this.x = x}};
<script type="text/javascript">let username = 'kobe';let age = 39;let obj = {username: username,age: agegetName: function () {return this.username;}};/* 在ES6中 */let obj = {username, /* 同名的属性可以省略不写 */age, /* 同名的属性可以省略不写 */getName() { /* 函数的 : function 可以省略不写 */return this.username;}};</script>
箭头函数
* 作用: 定义匿名函数
* 基本语法:* 没有参数: () => console.log('xxxx')* 一个参数: i => i+2* 大于一个参数: (i,j) => i+j* 函数体不用大括号: 默认返回结果* 函数体如果有多个语句, 需要用{}包围,若有需要返回的内容,需要手动返回
* 使用场景: 多用来定义回调函数* 箭头函数的特点:1、简洁2、箭头函数没有自己的this,箭头函数的this不是调用的时候决定的,而是在定义的时候处在的对象就是它的this,并且无法用 call() 、 apply() 、 bind() 改变。通俗理解: 箭头函数的this看外层的是否有函数,如果有,外层函数的this就是内部箭头函数的this,如果没有,则this是window。3、不能作为构造实例化对象4、不能使用 arguments 变量
<body><button id="btn">测试箭头函数this_1</button><button id="btn2">测试箭头函数this_2</button><script type="text/javascript">/* 函数的普通写法let fun = function () {console.log('我是箭头函数');}*//* 形参的情况 */// 1.没有形参的时候,()不能省略let fun1 = () => console.log('我是箭头函数');// 2.只有一个形参的时候,()可以省略let fun2 = (a) => console.log(a);let fun2 = a => console.log(a);// 3.两个及两个以上的形参的时候,()不能省略let fun3 = (x, y) => console.log(x, y); /* 函数体的情况 */// 1.函数体只有一条语句或者是表达式的时候,{}可以省略,此时会自动返回语句执行后的结果或者表达式的结果let fun4 = () => {console.log('我是箭头函数');}let fun4 = (x, y) => x + y;// 省略(),x+y 会自动执行let fun4 = (x, y) => {return x + y}; // 如果加上{},则需要用return来获取值// 2.函数体不止一条语句或表达式时,{}不可以省略let fun5 = (x, y) => {console.log(x, y);return x + y; // 需要return}/* 测试箭头函数的this *//* 箭头函数的this看外层的是否有函数(非箭头函数的函数),* 如果有,外层函数的this就是内部箭头函数的this,* 如果没有,则一直向上寻找直到this。*/let btn1 = document.getElementById('btn1');let btn2 = document.getElementById('btn2');btn1.onclick = function () {alert(this); // 结果为:btn1 谁调用,this就是谁}btn2.onclick = () => {alert(this); // 结果为:window 定义时所处的对象是window,所以this是window}let obj = {name: '箭头函数',getName: function () {btn2.onclick = () => {console.log(this);}}}obj.getName(); // 结果为:objlet obj = {name: '箭头函数',getName: () => { // 相当于obj.getName = () => {...};btn2.onclick = () => {console.log(this);}}}obj.getName(); // 结果为:window// 不能作为构造实例化对象let Person = (name, age) => {this.name = name;this.age = age;}let me = new Person('xiao', 30);console.log(me); // 报错:Uncaught TypeError: Person is not a constructor// 不能使用 arguments 变量let fn = () => {console.log(arguments)}fn(1, 2, 3); // 报错:Uncaught ReferenceError: arguments is not defined</script>
</body>
形参默认值
当不传入参数的时候默认使用形参里的默认值,如果有传入的值,则使用传入的值,如果没有传入值,则使用默认值。
一般来说,具有默认值的参数,位置在最后(潜规则)。
function Point(x=1, y=2) {this.x = x;this.y = y;
}
可以与解构赋值结合
<script type="text/javascript">// 定义一个点的坐标的构造函数function add(x, y=10) {return x + y;}let result1 = add(1, 2);let result2 = add(1);console.log(result1); // 3console.log(result2); // 11
</script>
rest参数
ES6 引入 rest 参数,用数组的方式获取函数的实参,用来代替 arguments 的对象形式,因此,可以用数组的方法更加灵活的操作实参。
注意:在ES6中,只针对于数组,在ES9中,则将范围扩展至数组和对象。
// arguments
function date(){console.log(arguments); // Arguments(2) [2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]console.log(typeof arguments); // arguments 本质为 objectarguments.forEach(function(item , index) { // 因为是arguments伪数组,因此使用数组的方式时会报错console.log(item, index);});
}
date(2, 3);// rest
function date(...args){console.log(args);let sum = 0;for(arg of args) { // args可以使用数组的相关方法操作实参sum += arg;}return sum;
}
date('d','e','f'); // 结果为数组 ["d", "e", "f"]// rest 参数必须要放到参数最后
function fn(a, ...args, b){...} // 报错
function fn(a, b, ...args){console.log(a);console.log(b);console.log(args);
}
fn(1, 2); // 结果:a=1,b=2
fn(1, 2, 3, 4, 5, 6); // 结果:a=1,b=2,args=[3, 4, 5, 6]
扩展运算符
能将数组转换为逗号分隔的参数序列。
注意:在ES6中,只针对于数组,在ES9中,则将范围扩展至数组和对象。
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
console.log(arr1); // 只有1个参数,为arr1数组本身[1, 2, 3]
console.log(...arr1); // 有3个参数,分别为 1 2 3// 数组的克隆与合并
let arr3 = [...arr1] // arr3: [1, 2, 3]
let arr4 = [4, ...arr1] // arr4: [4, 1, 2, 3]
let arr5 = [...arr1, ...arr2]; // arr5: [1, 2, 3, 4, 5, 6]
arr2.push(...arr1); // arr2: [4, 5, 6, 1, 2, 3]// 将伪数组转为真数组
const divs = document.querySelectorAll('div');
const divArr = [...divs]/** 为什么这样可以插入呢?* 扩展运算符实际上就是调用iterator接口,去遍历拿到arr3中的每一个值(详情见iterator接口机制)*/
Promise对象
关于Promise,更详细的见 Promise 笔记。
原理
1. 理解:* Promise对象: 代表了未来某个将要发生的事件(通常是一个异步操作)* 有了promise对象, 可以将异步操作以同步的流程表达出来, 避免了层层嵌套的回调函数(俗称'回调地狱')* ES6的Promise是一个构造函数, 用来生成promise实例
2. 使用promise基本步骤(2步):* 创建promise对象let promise = new Promise((resolve, reject) => {//初始化promise状态为 pending//执行异步操作if(异步操作成功) {resolve(value);//修改promise的状态为fullfilled} else {reject(errMsg);//修改promise的状态为rejected}})* 调用promise的then()promise.then(function(result => console.log(result),errorMsg => alert(errorMsg)))
3. promise对象的3个状态* pending: 初始化状态* fullfilled: 成功状态* rejected: 失败状态
4. 应用:* 使用promise实现超时处理* 使用promise封装处理ajax请求let request = new XMLHttpRequest();request.onreadystatechange = function () {}request.responseType = 'json';request.open("GET", url);request.send();
<script type="text/javascript">//创建一个promise实例对象let promise = new Promise((resolve, reject) => {//初始化promise的状态为 pending(初始化状态)console.log('111');//同步执行,先输出111,再输出222//执行异步操作,通常是发送ajax请求,开启定时器setTimeout(function () {console.log('333');/* 根据异步任务的返回结果来修改promise的状态 *///异步任务执行成功resolve('哈哈');//修改promise的状态为 fullfilled(成功状态),然后会自动调用then中的第一个函数,结果为:成功了 哈哈//异步任务执行失败reject('嘿嘿');//修改promise的状态为 rejected(失败状态),然后会自动调用then中的第二个函数,结果为:失败了 嘿嘿},2000)});/* 以下的data对应 resolve() 中的形参,error对应 reject() 中的形参 */promise.then((data) => {//第一个函数console.log('成功了 ' + data);//成功的回调}, (error) => {//第二个函数console.log('失败了 ' + error);//失败的回调});console.log('222');</script>
实例案例
对于网页中的新闻来说,一般上方是新闻的内容,下方是新闻的评论。新闻的内容肯定是要发请求给服务器从数据库获取的,那么怎么才能知道该拿的是哪一条新闻呢?在当初设置字段的时候会给每一个新闻都设置一个id,通过id寻找对应的新闻,那么下方的评论内容又怎么办呢,是新闻和评论一起请求还是先请求新闻内容再请求评论内容呢?将新闻内容和评论内容绑定到一起存入数据库,它们合在一起是一个字段,这当然没有问题,但有以下问题:1.不容易管理,数据量更大;2.有时候评论的内容比新闻的内容多得多,这时候,工作量会很大,如果浏览器渲染得慢,用户体验就不好,用户看到内容一点点地显示出来。而先请求新闻内容再请求评论内容的方式,有以下好处:1.数据少,页面渲染得快,这时,将新闻内容展现给用户的时间就会相对更短,用户体验更好,先让用户看到新闻内容,在用户看新闻内容的时候再发一次请求根据新闻内容的id找到相应评论的,再将评论渲染出来
/* 路由 */
router.get('/news', function (req, res, next) {res.set('Access-Control-Allow-Origin', '*');var id = req.query.id;console.log('/news id='+id);var news = {//假数据:当前的新闻内容id: id,title: 'news title1...',content: 'news content1...',commentsUrl: '/comments?newsId='+id//评论内容};res.json(news);//返回新闻内容数据
});router.get('/comments', function (req, res, next) {res.set('Access-Control-Allow-Origin', '*');console.log('/comments newsId=' + req.query.newsId);var newsId = req.query.newsId;var comments = [{id: 1,content: 'comment content1111...',newsId : newsId},{id: 2,content: 'comment content2222...',newsId : newsId}];res.json(comments);
});module.exports = router;
<script type="text/javascript">/* 需求:* 1、发送ajax请求获取新闻内容* 2、新闻内容获取成功后再次发送请求,获取对应的新闻评论内容* 3、新闻内容获取失败则不需要再次发送请求。*/ //定义获取新闻的功能函数function getNews(url) {let promise = new Promise((resolve, reject) => {//初始化promise状态为pending//启动异步任务//创建xmlHttp实例对象let xmlHttp = new XMLHttpRequest();//绑定监听 readyStatexmlHttp.onreadystatechange = function () {if(xmlHttp.readyState === 4){if(xmlHttp.status === 200){//请求成功//修改状态resolve(xmlHttp.responseText);//修改promise的状态为成功状态}else{//请求失败reject('暂时没有新闻内容');//修改promise的状态为失败状态}}};//open 设置请求的方式以及urlxmlHttp.open('GET', url);//发送xmlHttp.send();})return promise;}getNews('http://localhost:3000/news?id=2').then((data) => {//请求成功console.log(data);//发送请求获取评论内容准备urllet commentsUrl = JSON.parse(data).commentsUrl;let url = 'http://localhost:3000' + commentsUrl;//发送请求return getNews(url);}, (error) => {//请求失败console.log(error);}).then((data) => {console.log(data);}, (error) => {console.log(error);}) </script>
/* 老师的备课笔记 */
//定义一个请求news的方法
function getNews(url) {//创建一个promise对象let promise = new Promise((resolve, reject) => {//初始化promise状态为pending//启动异步任务let request = new XMLHttpRequest();request.onreadystatechange = function () {if(request.readyState === 4){if(request.status === 200){let news = request.response;resolve(news);}else{reject('请求失败了。。。');}}};request.responseType = 'json';//设置返回的数据类型request.open("GET", url);//规定请求的方法,创建链接request.send();//发送})return promise;
}getNews('http://localhost:3000/news?id=2').then((news) => {//请求成功console.log(news);document.write(JSON.stringify(news));console.log('http://localhost:3000' + news.commentsUrl);return getNews('http://localhost:3000' + news.commentsUrl);}, (error) => {//请求失败alert(error);}).then((comments) => {console.log(comments);document.write('<br><br><br><br><br>' + JSON.stringify(comments));}, (error) => {alert(error);})
使用promise基本步骤(2步):* 创建promise对象let promise = new Promise((resolve, reject) => {//初始化promise状态为 pending//执行异步操作if(异步操作成功) {resolve(value);//修改promise的状态为fullfilled} else {reject(errMsg);//修改promise的状态为rejected}})* 调用promise的then()promise.then(function(result => console.log(result),errorMsg => alert(errorMsg)))
3. promise对象的3个状态* pending: 初始化状态* fullfilled: 成功状态* rejected: 失败状态
4. 应用:* 使用promise实现超时处理* 使用promise封装处理ajax请求let request = new XMLHttpRequest();request.onreadystatechange = function () {}request.responseType = 'json';request.open("GET", url);request.send();
Symbol属性
前言:ES5中对象的属性名都是字符串,容易造成重名,污染环境Symbol:概念:ES6中的添加了一种原始数据类型symbol(已有的原始数据类型:String, Number, boolean, null, undefined, 对象)特点:1、Symbol属性对应的值是唯一的,解决命名冲突问题,最大的用法是用来定义对象的唯一属性名。2、Symbol值不能与其他数据进行计算,包括同字符串拼串。3、for in, for of遍历时不会遍历Symbol属性,但是可以使用 Reflect.ownKeys 来获取对象的所有键名。4、内置Symbol值除了定义自己使用的Symbol值以外,ES6还提供了11个内置的Symbol值,指向语言内部使用的方法。可以称这些方法为魔术方法,因为它们会在特定的场景下自动执行。5、Symbol.iterator对象的Symbol.iterator属性,指向该对象的默认遍历器方法(也可见iterator接口机制)
Symbol 内置值 | 作用 |
---|---|
Symbol.hasInstance | 当其他对象使用 instanceof 运算符,判断是否为该对象的实例时,会调用这个方法。 |
Symbol.isConcatSpreadable | 对象的 Symbol.isConcatSpreadable 属性等于的是一个布尔值,表示该对象用于 Array.prototype.concat()时,是否可以展开。 |
Symbol.species | 创建衍生对象时,会使用该属性。 |
Symbol.match | 当执行 str.match(myObject) 时,如果该属性存在,会调用它,返回该方法的返回值。 |
Symbol.replace | 当该对象被 str.replace(myObject)方法调用时,会返回该方法的返回值。 |
Symbol.search | 当该对象被 str. search (myObject)方法调用时,会返回该方法的返回值。 |
Symbol.split | 当该对象被 str. split (myObject)方法调用时,会返回该方法的返回值。 |
Symbol.iterator | 对象进行 for…of 循环时,会调用 Symbol.iterator 方法,返回该对象的默认遍历器。 |
Symbol.toPrimitive | 该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。 |
Symbol. toStringTag | 在该对象上面调用 toString 方法时,返回该方法的返回值。 |
Symbol. unscopables | 该对象指定了使用 with 关键字时,哪些属性会被 with 环境排除。 |
<script type="text/javascript">// 创建Symbol属性值let s1 = Symbol();console.log(s1, typeof s1); // Symbol() "symbol"// ()内可以传递用于标识作用的字符串let s2 = Symbol('abc');let s3 = Symbol('abc');console.log(s2); // Symbol(abc)console.log(s3); // Symbol(abc)console.log(s2 === s3); // false 两者不同let s4 = Symbol.for('def');let s5 = Symbol.for('def');console.log(s4); // Symbol(def)console.log(s5); // Symbol(def)console.log(s4 === s5); // true 通过Symbol.for()创建的则两者相同// 不能进行运算,包括同字符串拼串let result1 = s1 + 100; // 报错 Uncaught TypeError: Cannot convert a Symbol value to a numberlet result2 = s1 + 'a'; // 报错 Uncaught TypeError: Cannot convert a Symbol value to a string// 用作对象的属性(唯一)let obj = {username: 'kobe', age: 39};// obj.sex = '男';// obj.Symbol // 错误写法obj[symbol] = 'symbol';console.log(obj);//结果为:{username: "kobe", age: 39, Symbol(): "symbol"}obj[symbol] = 'hello';console.log(obj);//结果为:{username: "kobe", age: 39, Symbol(): "hello"}//for in、for of 不能遍历symbol属性。console.log(obj); // 结果为:{username: "kobe", age: 39, Symbol(): "hello"}for(let i in obj){console.log(i); // 结果为:username age 没有Symbol属性}// 向对象中添加方法 up downlet game = {name:'game',up: function() {},down: function() {}};// 方式一let methods = {up: Symbol(), down: Symbol()};game[methods.up] = function() {console.log("up");}game[methods.down] = function() {console.log("down");}console.log(game); // {name: "game", up: ƒ, down: ƒ, Symbol(): ƒ, Symbol(): ƒ}// 方式二let youxi = {name:"youxi",[Symbol('up')]: function(){ // Symbol('say')是一个表达式,需要用[]console.log("up")},[Symbol('down')]: function(){console.log('down');}}console.log(youxi) // {name: "youxi", Symbol(up): ƒ, Symbol(down): ƒ}// 内置值使用示例class Person{// 自己控制类型检测的结果static [Symbol.hasInstance](param){console.log(param); // ["a", "b"]return true;}}let o = ["a", "b"];console.log(o instanceof Person); // true 因为 [Symbol.hasInstance] return true,所以这里的结果也是 trueconst arr = [1,2,3];const arr2 = [4,5,6];arr2[Symbol.isConcatSpreadable] = false; // 设置为不可展开console.log(arr.concat(arr2)); // [1, 2, 3, Array(3)]</script>
/* 对象的Symbol.iterator属性,指向该对象的默认遍历器方法(后边讲)(见iterator接口机制) */
//使用三点运算符,解构赋值,默认去调用iterator接口
let arr2 = [1, 6];
let arr3 = [2, 3, 4, 5];
arr2 = [1, ...arr3, 6];
console.log(arr2);//结果为:[1, 2, 3, 4, 5, 6]/** 为什么这样可以插入呢?* 实际上就是调用iterator接口,去遍历拿到arr3中的每一个值*/let [a, b] = arr2;
console.log(a, b);//结果为:1 2
/** 同理,也是调用iterator接口进行遍历*/
iterator接口机制
概念: iterator是一种接口机制,为各种不同的数据结构提供统一的访问机制(这里的接口实际上是对象中的一个属性,属性名称是 Symbol.iterator,是一个函数)。作用:1、为各种数据结构,提供一个统一的、简便的访问接口2、使得数据结构的成员能够按某种次序排列,自定义遍历数据,重写[Symbol.iterator]()3、ES6创造了一种新的遍历命令 for of 循环,Iterator接口主要供 for of 消费工作原理:- 创建一个指针对象(遍历器对象),指向数据结构的起始位置。let iterator = MyArray[Symbol.iterator]();- 第一次调用next方法(指针对象中自带有),指针自动指向数据结构的第一个成员iterator.next();- 接下来不断调用next方法,指针会一直往后移动,直到指向最后一个成员- 每调用next方法返回的是一个包含value和done的对象,{value: 当前成员的值, done: 布尔值}* value表示当前成员的值,done对应的布尔值表示当前的数据的结构是否遍历结束* 当遍历结束的时候返回的value值是undefined,done值为true,否则为false原生具备iterator接口的数据(可用 for of 遍历):1、Array2、arguments3、set容器4、map容器5、String6、TypedArray7、NodeList
<script type="text/javascript"> /* 手动模拟ES6中的iterator是如何实现的 */// 模拟指针对象(遍历器对象)function myIterator (arr) { // iterator接口let nextIndex = 0; // 记录指针的位置return { // 遍历器对象next() { // 定义next方法return nextIndex < arr.length ? {value: arr[nextIndex++], done: false} : {value: undefined, done: true};}}}// 准备数据let arr = [1, 4, 65, 'abc'];let iteratorObj = myIterator(arr);console.log(iteratorObj.next()); // {value: 1, done: false}console.log(iteratorObj.next()); // {value: 4, done: false}console.log(iteratorObj.next()); // {value: 65, done: false}console.log(iteratorObj.next()); // {value: "abc", done: false}console.log(iteratorObj.next()); // {value: undefined, done: true}/* ------------------------------ */// 遍历数组for(let i of arr){console.log(i); // 1 4 65 abc}// 遍历字符串let str = 'abcdefg';for(let i of str){console.log(i); // a b c d e f g}// 遍历argumentsfunction fun() {for(let i of arguments){console.log(i);}}fun(1, 4, 5, 'abc'); // 1 4 5 abc// 遍历普通对象let obj = {username: 'kobe', age: 39}for(let i of obj){console.log(i); //报错:Uncaught TypeError: obj is not iterable} /* ------------------------------ *//* 重写iterator接口,自定义遍历 */// 当使用 for of 去遍历某一个数据结构的时候,首先去找Symbol.iterator,找到了就去遍历,没有找到的话则不能遍历: xxx is not iterableconst arr = {name: "arr",stus: ['a', 'b', 'c', 'd'],[Symbol.iterator]() {//索引变量let index = 0return {next: () => { // 定义next方法if (index < this.stus.length) {const result = { value: this.stus[index], done: false }index++; // 下标自增return result}else{return { value: undefined, done: true }}}}}}//遍历这个对象 for(let v of arr) {console.log(v); // a b c d}</script>
Generator函数
概念:1、ES6提供的解决异步编程的方案之一2、Generator函数是一个状态机,内部封装了不同状态的数据,3、用来生成遍历器对象4、可暂停函数(惰性求值), yield可暂停,next方法可启动。每次返回的是yield后的表达式结果
特点:1、function 与 函数名 之间有一个星号(*)2、内部用yield表达式来定义不同的状态例如:function * generatorExample() {let result = yield 'hello'; // 状态值为helloyield 'generator'; // 状态值为generator}3、generator函数返回的是指针对象(iterator接口机制),而不会执行函数内部逻辑4、调用next方法函数内部逻辑开始执行,遇到yield表达式停止,并返回一个对象,包含下一个yield的信息{value: 【yield后的表达式结果/undefined】, done: 【false/true】}5、再次调用next方法会从上一次停止时的yield处开始6、yield语句返回结果通常为undefined,next()中可以传入参数,用于下一步操作,传入的参数包含在yield的结果中,定义变量进行接收。
<script type="text/javascript">function * myGenerator() {console.log('aaa');yield 'hello';yield 'generator';}myGenerator(); // 可以发现:console.log('aaa') 并没有执行。因为yield会暂停,返回一个指针对象/* yield暂停,next方法启动。每次返回的是yield后的表达式结果 */function* myGenerator() {console.log('aaa');yield 'yield1';console.log('bbb');yield 'yield2';console.log('ccc');return 'ddd'// 用return来指定返回的值,如果不指定,则最后的yield信息的vuale值为undefined}let MG = myGenerator(); // 返回的是指针对象console.log(MG); // myGenerator {<suspended>}MG.next(); // aaa// next()返回下一个yield的信息let result1 = MG.next(); // bbbconsole.log(result1); // {value: "yield2", done: false}let result2 = MG.next(); // cccconsole.log(result2); // {value: "ddd", done: true}/* ------------------------------- */function* aa() {console.log(111)let result1 = yield 'yield1';console.log(222)console.log(result1); // undefined(默认值,yield默认返回的是undefined)let result2 = yield 'yield2' // 传入的参数包含在yield的结果中,定义变量进行接收console.log(333)console.log(result2); // ggggg next()中传入的值可以在这里进行操作yield 'yield3'console.log(444)}let AA = aa();console.log(AA); // aa {<suspended>}let result1 = AA.next(); // 111 并返回下一个yield的信息console.log(result1); // {value: "yield1", done: false}// 如果没有在next()中传入参数,则使当前暂停的yield的返回值默认为undefinedlet result2 = AA.next(); // 222// console.log(result1);输出结果为undefined,因为next()没有给yield1传入参数console.log(result2); // {value: "yield2", done: false} 下一个yield的信息// next()中可以传入参数,用于下一步操作,传入的参数包含在yield的结果中let result3 = AA.next('ggggg'); // 333// console.log(result2);输出结果为ggggg,因为next()中传入了参数console.log(result3); // {value: yield3, done: true} 下一个yield的信息let result4 = AA.next(); // 444console.log(result4); // {value: undefined, done: true} 下一个yield的信息</script>
let obj = {username: 'kobe', age: 39}
for(let i of obj){console.log(i); // 报错:Uncaught TypeError: obj is not iterable
}// 对象的Symbol.iterator属性,指向遍历器对象
// 人为地部署一个iterator接口,当使用 for of 遍历时,默认也是用遍历器对象去调用next()方法进行遍历Generator函数
let obj = {username: 'kobe', age: 39}
obj[Symbol.iterator] = function* myText() {yield 1;yield 2;yield 3;
}
for(let i of obj){console.log(i); // 1 2 3
}
应用
/* 引入jquery */
<script type="text/javascript" src="./js/jquery-1.10.1.min.js"></script><script type="text/javascript">/** 需求:* 1、发送ajax请求获取新闻内容* 2、新闻内容获取成功后再次发送请求,获取对应的新闻评论内容* 3、新闻内容获取失败则不需要再次发送请求。* */ function getNews(url) {$.get(url, function(data) {console.log(data);let commentsUrl = data.commentsUrl;let url = 'http://localhost:3000' + commentsUrl;// 当获取新闻内容成功,发送请求获取对应的评论内容// 调用next传参会作为上次暂停时yield的返回值sx.next(url);})}function* sendXml() {// url为next传参进来的数据let url = yield getNews('http://localhost:3000/news?newsId=2'); // 发请求拿到新闻newsyield getNews(url); // 发请求拿到评论内容comments}let sx = sendXml(); // 获取遍历器对象sx.next(); // 发送请求获取新闻内容/* ---------------------------------- *//* 模拟 先后获取 用户数据、订单数据、商品数据 解决回调地狱 */function getUsers(){setTimeout(()=>{let data = '用户数据';iterator.next(data); // 调用 next 方法, 并且将数据传入}, 1000);}function getOrders(){setTimeout(()=>{let data = '订单数据';iterator.next(data); // 调用 next 方法, 并且将数据传入}, 1000)}function getGoods(){setTimeout(()=>{let data = '商品数据';iterator.next(data); // 调用 next 方法, 并且将数据传入}, 1000)}function * gen(){let users = yield getUsers(); // 获取用户数据console.log(users); // 操作用户数据let orders = yield getOrders(); // 获取订单数据console.log(orders); // 操作订单数据let goods = yield getGoods(); // 获取商品数据console.log(goods); // 操作商品数据}// 调用生成器函数let iterator = gen();iterator.next();</script>
Class类
ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过 class 关键字,可以定义类。基本上,ES6 的 class 可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
1. class 定义类/实现类的继承
2. constructor 在类中通过定义构造方法
3. new 来创建类的实例
4. extends 实现类的继承
5. super 调用父类的构造方法
6. 重写从父类中继承的一般方法
// 先来看以前的写法
function Person(name , age) {this.name = name;this.age = age;
}
let person = new Person('kobe', 39);
console.log(person); // 结果如下图
结果如下图所示:
可以发现,在 _proto_
中有 constructor
因此 在类class中定义的所有方法都会放在原型上
,这样做的好处是只在内存中占一个位置,每生成一个实例,都可以去用这个方法。
// class的写法
// 定义一个人物的类
class Person {// 类的构造方法,在new的时候自动执行constructor(name, age) {this.name = name;this.age = age;}// 类的一般方法// 在class中`必须`使用对象的简写方式,省略函数的functionshowName() {console.log(this.name);}
}
let person = new Person('kobe', 39);
console.log(person); // 结果如下图
person.showName(); // kobe
结果如下图所示:
静态成员
function Phone(){}
Phone.name = '手机';
Phone.call = function(){console.log("打电话");
}Phone.prototype.aaa = 'aaa';let phone = new Phone();console.log(phone.name); // undefined
console.log(phone.aaa); // aaa/*实例对象与函数对象是不相通的,实例对象与函数对象的prototype才是相通的,因此可以访问 `phone.aaa`像 Phone.name、Phone.call 这样不属于实例对象的,就称为 '静态属性' 。在面向对象中,就是 属于类而不属于实例对象
*/class Phone{// 静态属性,用 static 声明,属于类而不属于实例对象static name = '手机';static change(){console.log("打电话");}
}let nokia = new Phone();console.log(nokia.name); // undefined
console.log(Phone.name); // 手机
继承
// 定义一个人物的类,父类
class Person {constructor(name, age) { // 注意:构造函数不是必须的this.name = name;this.age = age;}showName() {console.log('这是父类的showName'); console.log(this.name);}
}let person = new Person('kobe', 39);
console.log(person); // Person {name: "kobe", age: 39}
person.showName(); // 这是父类的showName kobe// 子类
// 用 extends 继承父类
class StarPerson extends Person {constructor(name, age, salary) {// 用 super() 先调用父类的构造方法,相当于父类中的 this.name = name; this.age = age;super(name, age);this.salary = salary;}// 重写父类的方法,与父类的方法同名即可。showName(){console.log('这是子类的showName');console.log(this.name, this.age, this.salary);}
}
let p1 = new StarPerson('wade', 36, 100000000);
console.log(p1); // StarPerson {name: "wade", age: 36, salary: 100000000}
p1.showName(); // 这是子类的showName wade 36 100000000
结果如下图所示:
/* 用ES5的方式实现构造函数继承 */
// 手机,父类
function Phone(brand, price) {this.brand = brand;this.price = price;
}Phone.prototype.call = function() {console.log("我可以打电话");
}// 智能手机,子类
function SmartPhone(brand, price, color, size) {Phone.call(this, brand, price);this.color = color;this.size = size;
}// 设置子级构造函数的原型
SmartPhone.prototype = new Phone;
SmartPhone.prototype.constructor = SmartPhone;// 声明子类的方法
SmartPhone.prototype.photo = function() {console.log("我可以拍照")
}
SmartPhone.prototype.playGame = function() {console.log("我可以玩游戏");
}const chuizi = new SmartPhone('锤子',2499,'黑色','5.5inch');console.log(chuizi); // SmartPhone {brand: "锤子", price: 2499, color: "黑色", size: "5.5inch"}
getter和setter
class Phone{get price(){console.log("价格被读取了");return 'iloveyou';}set price(newVal){console.log('价格被修改了');}
}//实例化对象
let s = new Phone();console.log(s.price); // 价格被读取了 iloveyou
s.price = 'free'; // 价格被修改了
字符串方法扩展
1. includes(str) 判断是否包含指定的字符串
2. startsWith(str) 判断是否以指定字符串开头
3. endsWith(str) 判断是否以指定字符串结尾
4. repeat(count) 重复指定次数
<script type="text/javascript">let str = 'abcdefg';/* includes(str) : 判断是否包含指定的字符串 */console.log(str.includes('a'));//结果为:trueconsole.log(str.includes('h'));//结果为:false/* startsWith(str) : 判断是否以指定字符串开头 */console.log(str.startsWith('a'));//结果为:trueconsole.log(str.startsWith('d'));//结果为:false/* endsWith(str) : 判断是否以指定字符串结尾 */console.log(str.endsWith('g'));//结果为:trueconsole.log(str.endsWith('d'));//结果为:false/* repeat(count) : 重复指定次数 */console.log(str.repeat(5));//结果为:abcdefgabcdefgabcdefgabcdefgabcdefg</script>
数值方法扩展
1. 二进制与八进制数值表示法: 二进制用0b, 八进制用0o
2. Number.isFinite(i) 判断是否是有限大的数
3. Number.isNaN(i) 判断是否是NaN
4. Number.isInteger(i) 判断是否是整数
5. Number.parseInt(str) 将字符串转换为对应的数值
6. Math.trunc(i) 直接去除小数部分
7. Math.sign() 判断一个数是正数、负数、0
8. Number.EPSILON 是 JavaScript 表示的最小精度
<script type="text/javascript">/* 二进制与八进制 */console.log(0b1010); // 10 二进制console.log(0o56); // 46 八进制/* Number.isFinite(i) 判断是否是有限大的数 */console.log(Number.isFinite(NaN)); // falseconsole.log(Number.isFinite(5)); // true/* Number.isNaN(i) 判断是否是NaN */console.log(Number.isNaN(NaN)); // trueconsole.log(Number.isNaN(5)); // falsse/* Number.isInteger(i) 判断是否是整数 */console.log(Number.isInteger(5.23)); // falseconsole.log(Number.isInteger(5.0)); // trueconsole.log(Number.isInteger(5)); // true/* Number.parseInt(str) 将字符串转换为对应的数值 */console.log(Number.parseInt('123abc')); // 123console.log(Number.parseInt('a123abc')); // NaN/* Math.trunc(i) 直接去除小数部分 */console.log(Math.trunc(13.123)); // 13console.log(Math.trunc(13.789)); // 13/* Math.sign() 判断一个数是正数、负数、0 */console.log(Math.sign(100)); // 1console.log(Math.sign(0)); // 0console.log(Math.sign(-20)); // -1/* Number.EPSILON 是 JavaScript 表示的最小精度 *//* 值接近于 2.2204460492503130808472633361816E-16 */// 主要用于浮点数的运算console.log(0.1 + 0.2); // 0.30000000000000004 不等于 0.3// 判断2个数是否相等function equal(a, b){if(Math.abs(a-b) < Number.EPSILON){return true;}else{return false;}}console.log(equal(0.1 + 0.2, 0.3)) // true</script>
数组方法扩展
1. Array.from(v) : 将伪数组对象或可遍历对象转换为真数组
2. Array.of(v1, v2, v3) : 将一系列值转换成数组
3. find(function(value, index, arr){return true}) : 找出第一个满足条件返回true的元素
4. findIndex(function(value, index, arr){return true}) : 找出第一个满足条件返回true的元素下标
<body><button>测试1</button><button>测试2</button><button>测试3</button><script type="text/javascript">/* Array.from(v) : 将伪数组对象或可遍历对象转换为真数组 */let btns = document.getElementsByTagName('button');// btns.forEach(function (item, index) {// console.log(item);//报错,因为这是伪数组,没有数组的一般方法// })Array.from(btns).forEach(function (item, index) {console.log(item);//结果为:<button>测试1</button> <button>测试2</button> <button>测试3</button> })/* Array.of(v1, v2, v3) : 将一系列值转换成数组 */let arr = Array.of(1, 4, 'abc', true);console.log(arr);//结果为:(4) [1, 4, "abc", true]/* find(function(value, index, arr){return true}) : 找出第一个满足条件返回true的元素 */let arr2 = [2, 3, 4, 2, 5, 7, 3, 6, 5];let result = arr2.find(function (item, index) {return item > 4});console.log(result);//结果为:5/* findIndex(function(value, index, arr){return true}) : 找出第一个满足条件返回true的元素下标 */let arr3 = [1, 2, 3, 4, 5, 6, 7];let result2 = arr3.findIndex(function (item, index) {return item > 4});console.log(result2);//结果为:4</script>
</body>
对象方法扩展
1. Object.is(v1, v2) 判断2个数据是否完全相等
2. Object.assign(target, source1, source2..) 将源对象的属性复制到目标对象上
3. Object.setPrototypeOf 设置原型对象
4. 直接操作 __proto__ 属性 let obj2 = {}; obj2.__proto__ = obj1;
<script type="text/javascript">/* Object.is(v1, v2) */console.log(0 === -0); // trueconsole.log(NaN === NaN); // false// Object.is(v1, v2)底层以字符串的形式来判断console.log(Object.is(0, -0)); // falseconsole.log(Object.is(NaN, NaN)); // true/* Object.assign(target, source1, source2..) */let obj1 = {};let obj2 = {};let obj3 = {username: 'anverson', age: 42};let obj4 = {sex: '男'};Object.assign(obj1, obj3);console.log(obj); // {username: "anverson", age: 42}Object.assign(obj2, obj3, obj4);console.log(obj); // {username: "anverson", age: 42, sex: "男"}/* 直接操作 __proto__ 属性 */let obj3 = {};let obj4 = {qian: 50000000};obj3.__proto__ = obj4;console.log(obj3.qian); // 50000000 .qian在__proto__中console.log(obj3); // 结果如下图所示/* Object.setPrototypeOf 设置原型对象 */const aaa = {foo: 'aaaa'}const bbb = {bar: 'bbbb'}// 2个参数表示改变,第1个参数要改变为目标,第2个参数为值Object.setPrototypeOf(aaa, bbb); // aaa 的 原型对象 变为 ["a", "b", "c"]// 1个参数时表示获取原型对象console.log(Object.getPrototypeOf(aaa)); // 见下图console.log(aaa); // 见下图</script>
结果如下图所示:
深度克隆
1、数据类型:* 数据分为基本的数据类型(String, Number, boolean, Null, Undefined)和对象数据类型- 基本数据类型:特点: 存储的是该对象的实际数据- 对象数据类型:特点: 存储的是该对象在栈中引用,真实的数据存放在堆内存里
2、复制数据- 基本数据类型存放的就是实际的数据,可直接复制let number2 = 2;let number1 = number2;- 克隆数据:对象/数组1、区别: 浅拷贝/深度拷贝判断: 拷贝是否产生了新的数据还是拷贝的是数据的引用知识点:对象数据存放的是对象在栈内存的引用,直接复制的是对象的引用let obj = {username: 'kobe'}let obj1 = obj; // obj1 复制了obj在栈内存的引用2、常用的拷贝技术1). arr.concat(): 数组浅拷贝2). arr.slice(): 数组浅拷贝3). JSON.parse(JSON.stringify(arr/obj)): 数组或对象深拷贝, 但不能处理函数数据4). 浅拷贝包含函数数据的对象/数组5). 深拷贝包含函数数据的对象/数组
<script type="text/javascript">/* 堆内存与栈内存之间的操作 *///不会影响原数据let str = 'abcd';let str2 = str;console.log(str2);//结果为:abcdstr2 = '';console.log(str);//结果为:abcdlet bool1 = true;let bool2 = bool1;bool2 = false;console.log(bool1);//结果为:true//会影响原始数据let obj = {username: 'kobe', age: 39};let obj1 = obj;console.log(obj1);//结果为:{username: "kobe", age: 39}obj1.username = 'wade';console.log(obj.username);//结果为:wade//拷贝数组/对象 没有生成新的数据而是复制了一份引用let arr = [1, 4, {username: 'kobe', age: 39}];let arr2 = arr;arr2[0] = 'abcd';console.log(arr, arr2);//结果为:(3) ["abcd", 4, {…}] (3) ["abcd", 4, {…}]</script>
<script type="text/javascript">/** 拷贝数据:* 基本数据类型:* 拷贝后会生成一份新的数据,修改拷贝以后的数据不会影响原数据* 对象/数组:* 拷贝后不会生成新的数据,而是进行引用。修改拷贝以后的数据会影响原数据* * 拷贝数据的方法:* 1. 直接复制给一个变量 //浅拷贝,会影响原数据* 2. Object.assign() //浅拷贝* 3. Array.prototype.concat() //浅拷贝* 4. Array.prototypr.slice() //浅拷贝* 5. JSON.parse(JSON.stringify()) //深拷贝(深度克隆) 注意:拷贝的数据不能有函数* * 浅拷贝(对象/数组):* 特点:拷贝的引用,修改拷贝后的数据会影响原数据,使得原数据不安全* 因为对象数据存放的是对象在栈内存的引用,直接复制的是对象的引用,* 新的引用会对原来的堆内存中的数据产生影响* 深拷贝(深度克隆)* 特点:拷贝的时候生成新的数据,修改拷贝后的数据不会影响原数据* 如果遍历的时候拿到的某一项值不是基本数据类型,则继续对其遍历,* 直到这一项值中的全部基本类型*/let obj = {username: 'kobe'};/* Object.assign() */let obj2 = Object.assign(obj);console.log(obj2);//结果为:{username: "kobe"}obj.username = 'wade';console.log(obj);//结果为:{username: "wade"}/* Array.prototype.concat() */let arr = [1, 3, {username: 'kobe'}];let testArr = [2, 4];
// let arr2 = arr.concat(testArr);
// console.log(arr2);//结果为:(5) [1, 3, {…}, 2, 4]let arr2 = arr.concat();console.log(arr2);//结果为:(3) [1, 3, {…}]arr2[1] = 'a';console.log(arr);//结果为:(3) [1, 3, {…}] //可以发现,不影响原数据,没有影响的本质原因是 相当于遍历后拿到每一项的值//相当于 : arr2[0] = 1; 这是基本数据类型,所以才不会影响//arr[2] = {username: 'kobe'} 是可确定的//但是,如果是对象arr2[2].username = 'wade';console.log(arr);//username变为'wade' 说明影响原数据/* Array.prototypr.slice() */let arr3 = arr.slice();arr3[2].username = 'anverson';console.log(arr);//username变为'anverson' 说明影响原数据/* JSON.parse(JSON.stringify()) */let arr4 = JSON.parse(JSON.stringify(arr));//将arr变为JSON字符串后再转换为原生的数组console.log(arr4);//username为'anverson' 说明没有影响原数据arr4[2].username = 'duncan';console.log(arr4);//username为'duncan'/* JSON字符串 --> JS数组 ,数据类型发生变化,所以不会影响原数据 *//** 思考:* 如何实现深度拷贝(克隆)* 拷贝的数据里有对象/数组、* 拷贝的数据里不能有对象/数组,即使有对象/数组,可以继续遍历对象、数组拿到里边每一项值,* 一直到拿到的都是基本数据类型,然后再去复制,这就是深度拷贝(克隆)*///知识点储备/** 如何判断数据类型: arr --> Array null --> Null* 1. typeof返回的数据类型:String, Number, Boolean, Undefined. Object, Function* 2. Object.prototype.toString.call(obj) (取到最原始的toString,通过call去指定目标数据,从而检测出目标数据的数据类型)*/let result = 'abcd';console.log(Object.prototype.toString.call(result));//结果为:[object String]result = null;console.log(Object.prototype.toString.call(result));//结果为:[object Null]result = [1, 3];console.log(Object.prototype.toString.call(result));//结果为:[object Array]console.log(typeof Object.prototype.toString.call(result));//结果为:stringconsole.log(Object.prototype.toString.call(result).slice(8, -1));//结果为:Array//for in 循环let obj = {username:'kobe', age: 39};//对象for(let i in obj) {//枚举对象/* 枚举对象时拿到的是属性名 */console.log(i);//结果为:username age (属性名)}let arr = [1, 3, 'abc'];//数组for(let i in arr) {//枚举数组/* 枚举数组时拿到的是下标 */console.log(i);//结果为:0 1 2 (下标)}//定义检测数据类型的功能函数function checkedType(target) {return Object.prototype.toString.call(target).slice(8, -1);}
// console.log(checkedType(result));//结果为:Array//自己实现深度克隆 --> 对象/数组function clone(target) {//判断拷贝的数据类型\//初始化变量result 成为最终克隆的数据let result, targetType = checkedType(target);if(targetType === 'Object') {result = {};}else if(targetType === 'Array'){result = [];}else{return target;}//遍历目标数据for(let i in target){//获取遍历数据结构的每一项值let value = target[i];//判断目标结构里的每一项值是否存在对象/数组,如果是对象/数组,则需要继续遍历if(checkedType(value) === 'Object' || checkedType(value) === 'Array'){//对象/数组里嵌套了对象/数组//继续遍历获取到的value值result[i] = clone(value);}else{//获取到的value值是基本的数据类型或者是函数result[i] = value;}}return result;}let arr3 = [1, 2, {username: 'kobe', age: 39}];let arr4 = clone(arr3);console.log(arr4);//结果为:1 2 {username: "kobe", age: 39, userName: "wade"}arr4[2].username = 'wade';console.log(arr3, arr4);//结果为:arr3的username为'kobe' arr4的username为'wade'let obj3 = {username: 'kobe', age: 39};let obj4 = clone(obj3);console.log(obj4);//结果为:{username: "kobe", age: 39}obj4.username = 'wade';console.log(obj3, obj4);//结果为:{username: "kobe", age: 39} {username: "wade", age: 39}</script>
Set 容器
Set容器:无序 不可重复 的多个value的集合体* new Set() 创建容器* Set(array) 将某个数组本身作为set容器的数据* [...new Set(array)] 得到某个数组中的所有元素去重后的新数组* add(value) 新增元素* delete(value) 删除元素* has(value) 检测是否包含某个元素,返回 boolean 值* clear() 清空集合,返回 undefined* .size 返回集合的元素个数
<script type="text/javascript">let set = new Set([1,2,4,5,3,6]); // 创建map容器console.log(set.size); // 6 返回集合的元素个数console.log(set); // Set(7) {1, 2, 4, 5, 3, 6} length为6 因为2重复了,自动去重console.log(set.has(7)); // falseset.add(7); // 新增console.log(set.has(7)); // trueconsole.log(set); // Set(7) {1, 2, 4, 5, 3, 6, 7}set.delete(7) // 删除console.log(set); // Set(6) {1, 2, 4, 5, 3, 6}// Set容器实现了iterator接口,可以使用 for of 遍历for(let i of set) {console.log(i); // 1 2 3 4 5 6}set.clear(); // 清空容器console.log(set); // Set(0) {}/* ----------------------- */let arr = [1,2,3,4,5,4,3,2,1];// 1. 数组去重let result1 = [...new Set(arr)];console.log(result1); // (5) [1, 2, 3, 4, 5] 自动去重// 2. 交集let arr2 = [4,5,6,5,6];let result2 = [...new Set(arr)].filter(item => new Set(arr2).has(item));console.log(result2); // (2) [4, 5]// 3. 并集let union = [...new Set([...arr, ...arr2])]; // 将2个数组合并后,利用Set容器去重后的数据再变为一个新数组console.log(union); // (6) [1, 2, 3, 4, 5, 6]// 4. 差集let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));console.log(diff); // (3) [1, 2, 3]</script>
Map 容器
Map容器:无序的key不重复的多个key-value的集合体“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键* new Map() 创建容器 * Map(array) 将某个数组本身作为set容器的数据* set(key, value) 新增键值对* get(key) 返回键名对象的键值* delete(key) 删除键值对* has(key) 检测 Map 中是否包含某个元素,返回 boolean 值* clear() 清空集合,返回undefined* .size 返回元素个数
<script type="text/javascript">let map = new Map([['aaa', 'username'], [36, 'age']]);console.log(map); // Map(2) {"aaa" => "username", 36 => "age"}map.set(78, 'haha'); // 新增console.log(map); // Map(3) {"aaa" => "username", 36 => "age", 78 => "haha"}map.delete(36); // 删除console.log(map); // Map(2) {"aaa" => "username", 78 => "haha"}console.log(map.size); // 2// Map容器实现了iterator接口,可以使用 for of 遍历for(let i of map) {console.log(i); // ["aaa", "username"] [78, "haha"]}map.clear(); // 清空console.log(map); // Map(0) {}</script>
for of 遍历
for(let value of target){}循环遍历1. 遍历数组2. 遍历Set容器3. 遍历Map容器4. 遍历字符串5. 遍历伪数组
<script type="text/javascript">let arr = [1,2,3,4,5];for(let i of arr) {console.log(i) // 1 2 3 4 5}</script>
ES7
** & includes
1. 指数运算符(幂): **
2. Array.prototype.includes(value) 判断数组中是否包含指定元素
<script type="text/javascript">console.log(3**3); // 27let arr = [1, 2, 3, 4, 'abc'];console.log(arr.includes(2)); // trueconsole.log(arr.includes(5)); // false</script>
ES8
async & await
概念: 真正意义上去解决异步回调的问题,让异步代码和同步代码一样async函数:async函数的返回值为一个Promise对象,且状态由return的结果决定await函数:await 必须写在 async 声明的函数中await 右侧的表达式一般为 Promise 对象await 返回的是 Promise 成功的值await 的 Promise 失败了, 就会抛出异常, 需要通过 try...catch 捕获处理
语法:async function foo(){await 异步操作;await 异步操作;}
本质: Generator的语法糖
特点:1、不需要像Generator去调用next方法,遇到await等待,当前的异步操作完成就往下执行2、返回的总是Promise对象,可以用then方法进行下一步操作3、async取代Generator函数的星号*,await取代Generator的yield4、语意上更为明确,使用简单,经临床验证,暂时没有任何副作用
<script type="text/javascript" src="./js/jquery-1.10.1.min.js"></script><script type="text/javascript">/* --------------- async的返回值 --------------- */async function bar() {return 'aaa'// return new Promise((resolve, reject) => {// resolve('成功');// });}const result = bar();/* async函数的返回值为一个Promise对象,且状态由return的结果决定async声明的函数中return的值只要不是一个Promise类型的对象,async的返回值就是一个成功状态的Promiseasync声明的函数中抛出错误,async的返回值就是一个失败状态的Promiseasync声明的函数中return一个Promise,则async的返回值也是一个Promise,且状态与return的Promise相同*/console.log(result); // Promise {<resolved>: "aaa"} /* --------------- await的返回值 --------------- */function test2() {return 'aaa';}async function asyncPrint() {/* 如果是普通的函数,返回值是await之后函数执行完的返回值 */let result1 = await test2();console.log(result1); // aaa/* 如果是Promise,返回值是Promise成功状态的值 */let result2 = await Promise.resolve('bbb');console.log(result2); // bbblet result3 = await Promise.resolve(); // 如果没有值,则返回undefinedconsole.log(result3); // undefined// 如果是reject状态,则报错,需要通过 try...catch 捕获处理 result4 = await Promise.reject('ccc');console.log(result4); // 报错:Uncaught (in promise) ccc}asyncPrint();/* --------------- 基本使用 --------------- */// 案例1async function foo() {return new Promise(resolve => {setTimeout(resolve, 2000);})}async function test() {/* 不需要使用Generator中的next()方法,可以直接开始执行 */console.log('开始执行', new Date().toTimeString()); // 开始执行 11:31:05 GMT+0800 (中国标准时间)await foo(); // 等待2sconsole.log('执行完毕', new Date().toTimeString()); // 2s后打印: 执行完毕 11:31:07 GMT+0800 (中国标准时间)}test();// 案例2// 发送 AJAX 请求, 返回的结果是 Promise 对象function sendAJAX(url) {return new Promise((resolve, reject) => {const x = new XMLHttpRequest(); // 创建对象x.open('GET', url); // 初始化x.send(); // 发送x.onreadystatechange = function () { // 事件绑定if (x.readyState === 4) {if (x.status >= 200 && x.status < 300) {resolve(x.response); // 成功}else{reject(x.status); // 失败}}}})}// Promise.then的方式sendAJAX("https://api.apiopen.top/getJoke").then(value => {console.log(value);}, reason=>{})// async与await的方式async function main(){let musics = await sendAJAX("https://api.apiopen.top/getJoke");console.log(musics);let tianqi = await sendAJAX('https://www.tianqiapi.com/api/?version=v1&city=%E5%8C%97%E4%BA%AC&appid=23941491&appsecret=TXoD5e8P')console.log(tianqi);}main();// 案例3/* 需求:* 1、发送ajax请求获取新闻内容* 2、新闻内容获取成功后再次发送请求,获取对应的新闻评论内容* 3、新闻内容获取失败则不需要再次发送请求。*/async function getNews(url) {return new Promise((resolve, reject) => {$.ajax({ // jQuerymethod: 'GET',url,success: data => resolve(data),error: error => reject(error)})})}async function sendXml(url) {let result1 = await getNews('http://localhost:3000/news?id=7');console.log(result1);if(!result1){ // 进行判断alert('暂时没有新闻可以推送');return;}let result2 = await getNews('http://localhost:3000' + result1.commentsUrl);console.log(result2);}sendXml();/* -- 案例3.应用技巧 -- */// 如果请求失败,作为用户是看不到控制台的反馈的,怎么修改才能使得,用户知道请求失败了呢?/* 只列出修改部分的代码 */success: data => resolve(data),// 将error也用resolve表示,然后可以将参数改为例如falseerror: error => resolve(false) // 此时,返回的是falseasync function sendXml(url) {let result1 = await getNews('http://localhost:3000000000/news?id=7'); // 改为错误的参数,此时result的结果为falseconsole.log(result1);if(!result1){ // 进行判断alert('暂时没有新闻可以推送');return;}result = await getNews('http://localhost:3000' + result.commentsUrl);console.log(result);}</script>
对象方法的扩展
const aaa = {name: "aaa",foo: ['a','b','c'],bar: [1, 2, 3, 4]
};// 获取对象所有的键
console.log(Object.keys(aaa)); // ["name", "foo", "bar"]// 获取对象所有的值
console.log(Object.values(aaa)); // ["aaa", ["a", "b", "c"], [1, 2, 3, 4]]// entries 获取对象所有的键值对,转化为二维数组 可用于创建 Map
console.log(Object.entries(aaa)); // [["name", "aaa"], ["foo", ['a','b','c']], ["bar", [1, 2, 3, 4]]]
const m = new Map(Object.entries(aaa));
console.log(m); // {"name" => "aaa", "foo" => Array(3), "bar" => Array(4)}
console.log(m.get('foo')); // ["a", "b", "c"]// 对象属性的描述对象
console.log(Object.getOwnPropertyDescriptors(aaa)); // 结果见下图// 可用于深层次对象的克隆的具体选项设置
const obj = Object.create(null, {name: {// 设置值value: 'bbb',// 属性特性writable: true, // 可修改configurable: true, // 可配置enumerable: true // 可枚举}
});
ES9
rest参数 & 扩展运算符
注意:在ES6中,rest参数 和 扩展运算符 只针对于数组,在ES9中,则将范围扩展至数组和对象。
// rest 参数
function connect({host, port, ...user}) {console.log(host); // 127.0.0.1console.log(port); // 3306console.log(user); // {username: "root", password: "root", type: "master"}
}connect({host: '127.0.0.1',port: 3306,username: 'root',password: 'root',type: 'master'
});// 对象合并
const Q = { q: '天音波' }
const W = { w: '金钟罩' }
const E = { e: '天雷破' }
const R = { r: '猛龙摆尾' }
const DF = { d: '惩戒', f: '闪现'}const mangseng = {...Q, ...W, ...E, ...R, ...DF};
console.log(mangseng); // {q: "天音波", w: "金钟罩", e: "天雷破", r: "猛龙摆尾", d: "惩戒", f: "闪现"}
正则扩展
命名捕获分组
//声明一个字符串
let str1 = '<a href="http://www.baidu.com">百度</a>';// 提取 url 与 『标签文本』
const reg1 = /<a href="(.*)">(.*)<\/a>/;// 执行
const result1 = reg1.exec(str1);// 需要使用下标
console.log(result1); // 见下图
console.log(result1[1]); // http://www.baidu.com
console.log(result1[2]); // 百度let str2 = '<a href="http://www.atguigu.com">尚硅谷</a>';
// 使用分组命名分组
const reg2 = /<a href="(?<aaa>.*)">(?<bbb>.*)<\/a>/;const result2 = reg2.exec(str2);// 不使用下标,而使用别名,这样可以避免下标变化导致的代码更改
console.log(result2); // 见下图
console.log(result2.groups.aaa); // http://www.atguigu.com
console.log(result2.groups.bbb); // 尚硅谷
反向断言
// 声明字符串 提取`555`
let str = 'JS5211314你知道么555啦啦啦';// 正向断言 根据目标`后面`的内容作唯一性的识别
const reg1 = /\d+(?=啦)/;
const result1 = reg1.exec(str);
console.log(result1); // 结果见下图// 反向断言 根据目标`前面`的内容作唯一性的识别
const reg2 = /(?<=么)\d+/;
const result2 = reg2.exec(str);
console.log(result2); // 结果见下图
dotAll模式
// dot . 元字符 除换行符以外的任意单个字符,减小换行符的干扰
let str = `
<ul><li><a>肖生克的救赎</a><p>上映日期: 1994-09-10</p></li><li><a>阿甘正传</a><p>上映日期: 1994-07-06</p></li>
</ul>`;// 声明正则 提取`肖生克的救赎`
const reg1 = /<li>\s+<a>(.*?)<\/a>\s+<p>(.*?)<\/p>/; // 换行符需要 \s
const reg2 = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/s; // 换行符用 .* 注意:末尾需要加上模式修正符 s// 执行匹配
const result1 = reg1.exec(str);
console.log(result1);
const result2 = reg2.exec(str);
console.log(result2);
ES10
对象方法扩展 Object.fromEntries
// Object.fromEntries 将二维数组转化为对象 可以看作 Object.entries ES8 的逆运算
const result1 = Object.fromEntries([['姓名', 'aaa'],['年龄', 18]
]);
console.log(result1); // {姓名: "aaa", 年龄: 18}// Object.entries ES8 将对象转化为二维数组
const arr = Object.entries({'姓名': "aaa",'年龄': 18
})
console.log(arr); // [["姓名", "aaa"], ["年龄", 18]]
字符串方法扩展 trimStart & trimEnd
// trim 清除字符串两侧的空白
let str = ' iloveyou ';console.log(str.trim()); // 'iloveyou'// trimStart() 清除字符串左侧的空白
console.log(str.trimStart()); // 'iloveyou '// trimEnd() 清除字符串右侧的空白
console.log(str.trimEnd()); // ' iloveyou'
数组方法扩展 flat & flatMap
// flat 将多维数组转化为低维数组
const arr1 = [1,2,3,4,[5,6]];
const arr2 = [1,2,3,4,[5,6,[7,8,9]]];
// 参数表示要下降的维度 默认为1 例如,三维数组.flat(2) 表示下降2个维度,变为一维数组
console.log(arr1.flat()); // [1, 2, 3, 4, 5, 6]
console.log(arr2.flat(1)); // [1, 2, 3, 4, 5, 6, [7, 8, 9]]
console.log(arr2.flat(2)); // [1, 2, 3, 4, 5, 6, 7, 8, 9]// flatMap 可以看作是 flat() 和 map() 方法的结合
const arr3 = [1, 2, 3, 4];const result1 = arr3.map(item => [item * 10]);
console.log(result1); // [[10], [20], [30], [40]] 二维数组const result2 = arr3.flatMap(item => [item * 10]);
console.log(result2); // [10, 20, 30, 40] 一维数组
Symbol.prototype.description
let s = Symbol('aaa');
console.log(s.description); // aaa
ES11
私有属性
class Person{// 公有属性name;// 私有属性,只能在类中访问#age;#weight;// 构造方法constructor(name, age, weight){this.name = name;this.#age = age;this.#weight = weight;}intro(){console.log(this.name); // 可以正常打印console.log(this.#age); // 可以正常打印console.log(this.#weight); // 可以正常打印}
}const girl = new Person('小红', 18, '45kg');console.log(girl.name); // 可以正常打印
console.log(girl.#age); // 报错:Uncaught SyntaxError: Private field '#age' must be declared in an enclosing class
console.log(girl.#weight); // 报错:Uncaught SyntaxError: Private field '#weight' must be declared in an enclosing classgirl.intro();
Promise.allSettled
使Promise始终成功,即始终会执行.then的第一个回调函数,并返回真正的状态和结果
参数是一组包含Promise实例的数组,返回值是一个新的Promise实例,其实例在调用then方法中的回调函数的参数仍是一个数组。适用场景:例如,3个接口分别显示3部分内容,如果使用Promise.allSettle,则即使其中有1/2个接口失效,仍然会有部分内容显示,只需过滤掉状态为rejected的数据即可;而如果使用Promise.all,则一旦其中有1个接口失效,则3个接口的数据全都无法获取,所有内容都无法显示。
const p1 = new Promise((resolve, reject) => {setTimeout(()=>{resolve('商品数据 - 1');},1000)
});const p2 = new Promise((resolve, reject) => {setTimeout(()=>{// resolve('商品数据 - 2');reject('出错啦!');},1000)
});const result = Promise.allSettled([p1, p2]);
console.log(result); // 结果见下图 fulfilled和resolve一样,表示成功Promise.allSettled([p1, p2]).then(args => {console.log(args); /* [{status: "fulfilled", value: "商品数据 - 1"}, {status: "rejected", reason: "出错啦!"}]*/
})// 过滤出成功的请求
const success = result.then(args => {const suc = args.filter(p => p.status === 'fulfilled');console.log(suc); // {status: "fulfilled", value: "商品数据 - 1"}
})// 过滤出失败的请求,并输出原因
const errors = result.then(args => {const err = args.filter(p => p.status === 'rejected').map(p => p.reason);console.log(err); // ["出错啦!"]
})
String.prototype.matchAll
// String.prototype.matchAll 用来得到正则批量匹配的结果let str = `<ul><li><a>肖生克的救赎</a><p>上映日期: 1994-09-10</p></li><li><a>阿甘正传</a><p>上映日期: 1994-07-06</p></li>
</ul>`;// 声明正则
const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/sgconst result = str.matchAll(reg);
console.log(result); // 结果见下图// 方式一
for(let v of result){console.log(v);
}// 方式二
const arr = [...result];
console.log(arr);
可选链操作符
// ?. 如果前面那个属性存在,则读取后面那个属性 避免多层判断
function main(config){// 之前的判断方法,如果不存在则报错const dbHost1 = config && config.db && config.db.host; // 使用可选链操作符,如果不存在则返回 undefined ,不会报错const dbHost2 = config?.db?.host;
}main({db: {host:'192.168.1.100',username: 'root'},cache: {host: '192.168.1.200',username:'admin'}
})
动态import
实现按需加载。
// app.js// import * as m1 from "./hello.js"; // 静态导入的方法
const btn = document.getElementById('btn');
btn.onclick = function(){// 动态加载,返回的是一个Promise对象import('./hello.js').then(module => { // 参数modele就是对应的export的对象module.hello();});
}
// hello.js
export function hello(){alert('Hello');
}
BigInt
// BigInt 大整型
let n = 521n; // n表示BigInt类型
console.log(n, typeof(n)); // 521n "bigint"// 函数 将整数变为BigInt类型
let n = 123;
console.log(BigInt(n)); // 123n
console.log(BigInt(1.2)); // 报错,只能是整数类型// BigInt主要用于大数值运算
let max = Number.MAX_SAFE_INTEGER;
console.log(max); // 9007199254740991
console.log(max + 1); // 9007199254740992 不能再表示更大的结果
console.log(max + 2); // 9007199254740992 不能再表示更大的结果console.log(BigInt(max)); // 9007199254740991n
console.log(BigInt(max) + 1); // 报错,BigInt不能与普通类型的整数运算
console.log(BigInt(max) + BigInt(1)); // 9007199254740992n
console.log(BigInt(max) + BigInt(2)); // 9007199254740993n
globalThis
始终指向全局对象。
console.log(globalThis); // Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}// 在node.js下则指向 global
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- torch下函数手动梯度计算
计算函数:y = x**2*e**x的导数公式code实现 公式 y(z)=x2ex,. y(z) = x^{2}e^{x},. y(z)=x2ex,. y′=2xex+x2ex,. y^{}= 2xe^{x}+x^{2}e^{x},. y′=2xex+x2ex,. 一般可以手动计算出导数的可导函数,可以手动求导。 学习torch,掌握tensor,autograd,Variable,nn,nn.Module,loss…...
2024/5/5 17:04:12 - 2020-07-14javaSE
超时自由 cdh mpp impala学习习惯很重要,复习,练习,今天学,明天复习,今月学,下月复习。每天学习一点点,不学点过意不去。一个半月。串javase,javaeeweb(servlet,jst,jstl)、过滤器、监听器、SSM。jvm,跨操作系统,跨硬件。 java源码编译成虚拟机需要的java字节码(…...
2024/5/5 20:24:44 - 对于ArrayList的底层原码的分析
对于ArrayList的底层原码的分析 1.基本属性 1.1两个object数组 Object[] EMPTY_ELEMENTDATA = {}; Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}空数组。 带有长度的数组–>不是很确定。1.2其他的初始值 默认的初始容量。 private static final int DEFAULT_CAPACITY …...
2024/4/26 8:17:52 - spring mail
https://blog.csdn.net/qq_34337272/article/details/81556772...
2024/4/21 13:22:41 - Python 序列类型2(元组tuple)
元组(tuple) 元组与列表相似,不同的是元组内的元素不可更改 列表与元组可以相互转换 使用元组的好处保护原始数据 获得较快的遍历速度1.元组的创建 tup=(1,2) tup1=(1,) tup2=(a,b,c)元组的创建只需在小括号内添加由逗号分割的元素即可 注:当元组内只有一个元素时,需在元素…...
2024/4/21 7:27:03 - Java词法分析器的设计与实现
“生活充满了选择,而生活的态度就是一切。”词法分析器的设计与实现 二级 学院:信息科学与技术学院 专 业:计算机科学与技术 班 级: xxxx 姓 名: 梦阳辰 学 号: xx 指导 老师: xx 成 绩: 词法分析器的设计与实现 目 录 摘 要-----------…...
2024/5/2 17:33:54 - Linux下安装Java(JDK8)
https://www.cnblogs.com/xianhan/p/10082543.html...
2024/4/9 18:48:39 - Vue常用代码
一、通过class、id获取对象var boxId = document.querySelector("#box");let obj = document.querySelector(.gd-modal-close) obj.addEventListener(click, function() {console.log(11111111111) })...
2024/4/25 0:35:29 - C/C++中强制类型的转换(static_cast)
发现个新的领域,参考代码:https://www.cnblogs.com/QG-whz/p/4509710.htmlhttps://blog.csdn.net/Yinghuhu333333/article/details/80722389double a = 1.999; int b = static_cast<double>(a); //相当于a = b ;这种是C++中特殊的强制转换方式,用的较多的就是这种,后…...
2024/5/5 18:27:49 - Redis场景应用及demo
Spring Boot 对常用的数据库支持外,对 Nosql 数据库也进行了封装自动化。 Redis 介绍 Redis 是目前业界使用最广泛的内存数据存储。相比 Memcached,Redis 支持更丰富的数据结构,例如 hashes, lists, sets 等,同时支持数据持久化。除此之外,Redis 还提供一些类数据库的特性…...
2024/4/9 19:14:06 - 第一篇
第一篇文档...
2024/4/23 3:00:37 - 转:月薪5千和月薪5W的offer,中间只差这一步
本系列转自“高胜寒|职场引路人”高老师的博客,高老师主页地址:https://blog.csdn.net/xinshuzhan 原文地址:https://blog.csdn.net/xinshuzhan/article/details/106311940 我实在是很喜欢老师的博客,所以就请求了老师的同意,进行转载本文关键词: 高薪、面试、offer、靠谱…...
2024/4/30 16:49:28 - python实现词云图
先看一下成果图:图片给大家,从某一篇帖子找的。需要使用的的库: matplotlib.pyplot 绘图展示 jeiba 分词 wordcloud.WordCloud 绘制词云 numpy 制作背景图 PIL.Image 制作背景图 不…...
2024/4/26 8:31:40 - python系统的安装和cnocr的安装以及它们各自的使用
Python3中cnocr的使用 简介:之前写了tesseract-ocr和百度ocr,索性这次就自学一下python中的cnoce 1.在Linux下安装Python3环境 https://www.cnblogs.com/lemon-feng/p/11208435.html 这个里面介绍的很全 2.在Python3环境下安装cnocr https://github.com/breezedeus/cnocr 注意…...
2024/4/23 5:41:31 - x264 码率控制
q = qp2qscale( ABR_INIT_QP ) / fabs( h->param.rc.f_ip_factor ); //qscale = qp2qscale ,将初始化的qp转换成qp值。#define ABR_INIT_QP (( h->param.rc.i_rc_method == X264_RC_CRF ? h->param.rc.f_rf_constant : 24 ) + QP_BD_OFFSET) //CRF模式,QP初始化值为…...
2024/5/5 19:31:01 - IQKeyboardManager 对UITableView 上布局的UITextFiled不起作用
IQKeyboardManager 对UITableView 上布局的UITextFiled不起作用 需要单独设置键盘 - (void)viewDidLoad {[super viewDidLoad];[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil…...
2024/4/9 19:14:01 - android studio 入门---做一个按键控制程序
android studio 入门---做一个按键控制程序程序比hello world复杂一点,主要功能就是按下 第一个按键,该按键颜色会变化,同时右下角edit框文字会有变化GUI布局是这样的源代码是这样的:package com.example.myapplication113;import androidx.appcompat.app.AppCompatActivit…...
2024/5/5 12:21:14 - JS数组去重的三种方法
在程序中,通常解决一个问题的方法有很多种。当然这些不同思路的解决方法,在性能和效率上也有很大差异。 以下是数字去重的三种方法,一、循环遍历法(传统思路) 最简单粗暴的算法,新建一个空数组,然后遍历原数组,将不在新数组中的项添加到新数组,最后返回新数组function…...
2024/4/26 22:05:19 - PAT A1125 Chain the Ropes (25)
PTA跳转:原题链接 题目大意:给出多段绳子的长度,要求把这些绳子连结在一起,求最终绳子的最大程度(向下取整)。其中,将绳子A和B连结在一起的长度为(A+B)/2。 解题思路:由于每次结绳都要取平均数,那么要让较长的绳子少结绳。递增排序即可实现这个效果。 做完之后想了一下…...
2024/4/9 19:13:57 - 牛客多校第一场 Minimum-cost Flow(最小费最大流)
题目链接 题意:给你一张有n个点m条边组组成的无向图,每条边的容量未知,但是给你每条边通过1流量所需要的花费,现在给你q个询问,每次询问的给你u,v表示将每条边的容量改为u/v,问你从1-n流过流量为1的最小花费是多少。 思路:很快就能想到这是个最小费最大流问题,但是询问…...
2024/4/22 12:29:38
最新文章
- 论文| Where Is Your Place, Visual Place Recognition?
论文| Where Is Your Place, Visual Place Recognition?...
2024/5/5 22:52:02 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/3/20 10:50:27 - C++ //练习 11.14 扩展你在11.2.1节练习(第378页)中编写的孩子姓到名的map,添加一个pair的vector,保存孩子的名和生日。
C Primer(第5版) 练习 11.14 练习 11.14 扩展你在11.2.1节练习(第378页)中编写的孩子姓到名的map,添加一个pair的vector,保存孩子的名和生日。 环境:Linux Ubuntu(云服务器&#x…...
2024/5/5 8:38:52 - C++ 【原型模式】
简单介绍 原型模式是一种创建型设计模式 | 它使你能够复制已有对象,客户端不需要知道要复制的对象是哪个类的实例,只需通过原型工厂获取该对象的副本。 以后需要更改具体的类或添加新的原型类,客户端代码无需改变,只需修改原型工…...
2024/5/5 8:37:55 - 416. 分割等和子集问题(动态规划)
题目 题解 class Solution:def canPartition(self, nums: List[int]) -> bool:# badcaseif not nums:return True# 不能被2整除if sum(nums) % 2 ! 0:return False# 状态定义:dp[i][j]表示当背包容量为j,用前i个物品是否正好可以将背包填满ÿ…...
2024/5/5 18:19:03 - 【Java】ExcelWriter自适应宽度工具类(支持中文)
工具类 import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet;/*** Excel工具类** author xiaoming* date 2023/11/17 10:40*/ public class ExcelUti…...
2024/5/5 12:22:20 - Spring cloud负载均衡@LoadBalanced LoadBalancerClient
LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon,直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件,我们讨论Spring负载均衡以Spring Cloud2020之后版本为主,学习Spring Cloud LoadBalance,暂不讨论Ribbon…...
2024/5/5 19:59:54 - TSINGSEE青犀AI智能分析+视频监控工业园区周界安全防范方案
一、背景需求分析 在工业产业园、化工园或生产制造园区中,周界防范意义重大,对园区的安全起到重要的作用。常规的安防方式是采用人员巡查,人力投入成本大而且效率低。周界一旦被破坏或入侵,会影响园区人员和资产安全,…...
2024/5/4 23:54:44 - VB.net WebBrowser网页元素抓取分析方法
在用WebBrowser编程实现网页操作自动化时,常要分析网页Html,例如网页在加载数据时,常会显示“系统处理中,请稍候..”,我们需要在数据加载完成后才能继续下一步操作,如何抓取这个信息的网页html元素变化&…...
2024/5/5 15:25:47 - 【Objective-C】Objective-C汇总
方法定义 参考:https://www.yiibai.com/objective_c/objective_c_functions.html Objective-C编程语言中方法定义的一般形式如下 - (return_type) method_name:( argumentType1 )argumentName1 joiningArgument2:( argumentType2 )argumentName2 ... joiningArgu…...
2024/5/4 23:54:49 - 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】
👨💻博客主页:花无缺 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】🌏题目描述🌏输入格…...
2024/5/4 23:54:44 - 【ES6.0】- 扩展运算符(...)
【ES6.0】- 扩展运算符... 文章目录 【ES6.0】- 扩展运算符...一、概述二、拷贝数组对象三、合并操作四、参数传递五、数组去重六、字符串转字符数组七、NodeList转数组八、解构变量九、打印日志十、总结 一、概述 **扩展运算符(...)**允许一个表达式在期望多个参数࿰…...
2024/5/4 14:46:12 - 摩根看好的前智能硬件头部品牌双11交易数据极度异常!——是模式创新还是饮鸩止渴?
文 | 螳螂观察 作者 | 李燃 双11狂欢已落下帷幕,各大品牌纷纷晒出优异的成绩单,摩根士丹利投资的智能硬件头部品牌凯迪仕也不例外。然而有爆料称,在自媒体平台发布霸榜各大榜单喜讯的凯迪仕智能锁,多个平台数据都表现出极度异常…...
2024/5/5 18:50:00 - Go语言常用命令详解(二)
文章目录 前言常用命令go bug示例参数说明 go doc示例参数说明 go env示例 go fix示例 go fmt示例 go generate示例 总结写在最后 前言 接着上一篇继续介绍Go语言的常用命令 常用命令 以下是一些常用的Go命令,这些命令可以帮助您在Go开发中进行编译、测试、运行和…...
2024/5/4 14:46:11 - 用欧拉路径判断图同构推出reverse合法性:1116T4
http://cplusoj.com/d/senior/p/SS231116D 假设我们要把 a a a 变成 b b b,我们在 a i a_i ai 和 a i 1 a_{i1} ai1 之间连边, b b b 同理,则 a a a 能变成 b b b 的充要条件是两图 A , B A,B A,B 同构。 必要性显然࿰…...
2024/5/5 2:25:33 - 【NGINX--1】基础知识
1、在 Debian/Ubuntu 上安装 NGINX 在 Debian 或 Ubuntu 机器上安装 NGINX 开源版。 更新已配置源的软件包信息,并安装一些有助于配置官方 NGINX 软件包仓库的软件包: apt-get update apt install -y curl gnupg2 ca-certificates lsb-release debian-…...
2024/5/4 21:24:42 - Hive默认分割符、存储格式与数据压缩
目录 1、Hive默认分割符2、Hive存储格式3、Hive数据压缩 1、Hive默认分割符 Hive创建表时指定的行受限(ROW FORMAT)配置标准HQL为: ... ROW FORMAT DELIMITED FIELDS TERMINATED BY \u0001 COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMI…...
2024/5/5 13:14:22 - 【论文阅读】MAG:一种用于航天器遥测数据中有效异常检测的新方法
文章目录 摘要1 引言2 问题描述3 拟议框架4 所提出方法的细节A.数据预处理B.变量相关分析C.MAG模型D.异常分数 5 实验A.数据集和性能指标B.实验设置与平台C.结果和比较 6 结论 摘要 异常检测是保证航天器稳定性的关键。在航天器运行过程中,传感器和控制器产生大量周…...
2024/5/4 13:16:06 - --max-old-space-size=8192报错
vue项目运行时,如果经常运行慢,崩溃停止服务,报如下错误 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 因为在 Node 中,通过JavaScript使用内存时只能使用部分内存(64位系统&…...
2024/5/5 17:03:52 - 基于深度学习的恶意软件检测
恶意软件是指恶意软件犯罪者用来感染个人计算机或整个组织的网络的软件。 它利用目标系统漏洞,例如可以被劫持的合法软件(例如浏览器或 Web 应用程序插件)中的错误。 恶意软件渗透可能会造成灾难性的后果,包括数据被盗、勒索或网…...
2024/5/5 21:10:50 - JS原型对象prototype
让我简单的为大家介绍一下原型对象prototype吧! 使用原型实现方法共享 1.构造函数通过原型分配的函数是所有对象所 共享的。 2.JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象,所以我们也称为原型对象…...
2024/5/5 3:37:58 - C++中只能有一个实例的单例类
C中只能有一个实例的单例类 前面讨论的 President 类很不错,但存在一个缺陷:无法禁止通过实例化多个对象来创建多名总统: President One, Two, Three; 由于复制构造函数是私有的,其中每个对象都是不可复制的,但您的目…...
2024/5/4 23:54:30 - python django 小程序图书借阅源码
开发工具: PyCharm,mysql5.7,微信开发者工具 技术说明: python django html 小程序 功能介绍: 用户端: 登录注册(含授权登录) 首页显示搜索图书,轮播图࿰…...
2024/5/5 17:03:21 - 电子学会C/C++编程等级考试2022年03月(一级)真题解析
C/C++等级考试(1~8级)全部真题・点这里 第1题:双精度浮点数的输入输出 输入一个双精度浮点数,保留8位小数,输出这个浮点数。 时间限制:1000 内存限制:65536输入 只有一行,一个双精度浮点数。输出 一行,保留8位小数的浮点数。样例输入 3.1415926535798932样例输出 3.1…...
2024/5/5 15:25:31 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...
2022/11/19 21:17:16 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在iPhone上关闭“请勿打扰”
Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...
2022/11/19 21:16:57