面向对象更贴近我们的实际生活,可以使用面向对象描述现实世界事物。
但是事物分为具体的事物和抽象的事物
抽取(抽象)对象共用的属性和行为组织(封装)一个类(模板)。
对类进行实例化, 获取类的对象。
面向对象编程我们考虑的是有哪些对象,按照面向对象的思维特点,不断的创建对象,使用对象,指挥对象做事情。
现实生活中:万物皆对象,对象是一个具体的事物,看得见摸
得着的实物。例如,一本书、一辆汽车、一个人可以是“对象”,
一个数据库、一张网页、一个与远程服务器的连接也可以是
“对象”。
在 JavaScript中,对象是一组无序的相关属性和方法的集合,
所有的事物都是对象,例如字符串、数值、数组、函数等。
在 ES6 中新增加了类的概念,可以使用class关键字声明一个类,之后以这个类来实例化对象。
注意: 类必须使用 new 实例化对象
constructor()方法是类的构造函数(默认方法),用于传递参
数,返回实例对象,通过new命令生成对象实例时,自动调用
该方法。
如果没有显示定义,类内部会自动给我们创建一个constructor()
class Star{
constructor(uname){
this.uame //指向创建的实例
}
}
2.利用类创建对象 new
new Star() //只要加了new,自动调用constructor
子类通过extends可以继承父类的一些属性和方法。
注意
继承中属性或者方法的查找原则:就近原则。
继承中,如果实例化子类输出一个方法,先看子类有没有这
个方法,如果有就先执行子类的;如果子类中没,就去父类
中查找,如果有,就执行父类中的这个方法(就近原则)。
class Father{ // 父类
conostrctor(){
}
money(){
console.log(100)
}
}
class Son extends Father { // 子类继承父类
}
var son=new Son();
son.money()
super 关键字用于访问和调用对象父类上的函数。可以调用父类的构造函数,也可以调用父类的普通函数。
注意
子类在构造函数中使用super, 必须放到 this 前面(必须先调用父类的构造方法,再使用子类构造方法)
class Father {
constructor(x, y) {
this.x = x;
this.y = y;
}
sum() {
console.log(this.x + this.y);
}
}
class Son extends Father {
constructor(x, y) {
super(x, y); //调用了父类中的构造函数
}
}
var son = new Son(1, 2);
var son1 = new Son(11, 22);
son.sum();
son1.sum();
super必须放到this前面
var that;
var _that;
class Star {
constructor(uname, age) {
// constructor 里面的this 指向的是 创建的实例对象
that = this;
console.log(this);
this.uname = uname;
this.age = age;
// this.sing();
this.btn = document.querySelector('button');
this.btn.onclick = this.sing;
}
sing() {
// 这个sing方法里面的this 指向的是 btn
这个按钮,因为这个按钮调用了这个函数
console.log(this);
console.log(that.uname);
// that里面存储的是constructor里面的this
}
dance() {
// 这个dance里面的this 指向的是实例对象
ldh 因为ldh 调用了这个函数
_that = this;
console.log(this);
}
}
var ldh = new Star('刘德华');
console.log(that === ldh);
ldh.dance();
console.log(_that === ldh);
// 1. 在ES6中类没有变量提升,所以必须先定义类,
才能通过类实例化对象
// 2. 类里面的共有的属性和方法一定要加this使用.
构造函数是一种特殊的函数,主要用来初始化对象,即为对
象成员变量赋初始值,它总与new一起使用。我们可以把对象
中一些公共的属性和方法抽取出来,然后封装到这个函数里面。
在 JS 中,使用构造函数时要注意以下两点:
JavaScript的构造函数中可以添加一些成员,可以在构造函数本身上添加,也可以在构造函数内部的this上添加。通过这两种方式添加的成员,就分别称为静态成员和实例成员。
function Star(){
this.name=name
this.age=age
this.sing=function(){
console.log(SSS)
}
}
var XXX=new Star("XX","YY")
//1.实例成员就是构造函数内部通过this添加的成员
name age sing 就是实例成员
// 实例成员只能通过实例化的对象来访问
console.log(XXX.name);
XXX.sing();
// console.log(Star.uname);
//不可以通过构造函数来访问实例成员
// 2. 静态成员 在构造函数本身上添加的成员 sex 就是静态成员
Star.sex = '男';
// 静态成员只能通过构造函数来访问
console.log(Star.sex);
console.log(ldh.sex); // 不能通过对象来访问
存在浪费内存的问题
function Star(uname, age) {
this.uname = uname;
this.age = age;
this.sing = function() {
console.log('我会唱歌');
}
}
var ldh = new Star('刘德华', 18);
var zxy = new Star('张学友', 19);
构造函数通过原型分配的函数是所有对象所共享的。
JavaScript 规定,每一个构造函数都有一个 prototype
属性,指向另一个对象。注意这个prototype就是一个对
象,这个对象的所有属性和方法,都会被构造函数所拥有。
我们可以把那些不变的方法,直接定义在 prototype
对象上,这样所有对象的实例就可以共享这些方法。
一般情况下,我们把公共属性定义到构造函数里面,公共的方法我们放到原型对象身上。
对象都会有一个属性 __ proto __ 指向构造函数的 prototype 原型对象,之所以我们对象可以使用构造函数 prototype 原型对象的属性和方法,就是因为对象有 __ proto __ 原型的存在。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9fUq2a9p-1599014941104)(https://github.com/BXsweetheart/youdaoNotes/blob/master/proto.png?raw=true)]
对象原型( __ proto __)和构造函数(prototype)原型对象里面都有一个属性 constructor 属性 ,constructor 我们称为构造函数,因为它指回构造函数本身。
constructor 主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来的构造函数。
一般情况下,对象的方法都在构造函数的原型对象中设置。如果有多个对象的方法,我们可以给原型对象采取对象形式赋值,但是这样就会覆盖构造函数原型对象原来的内容,这样修改后的原型对象 constructor就不再指向当前构造函数了。此时,我们可以在修改后的原型对象中,添加一个constructor指向原来的构造函数。
只要是对象就有__proto__ 原型, 指向原型对象
我们Star原型对象里面的__proto__原型指向的是 Object.prototype
我们Object.prototype原型对象里面的__proto__原型 指向为 null
可以通过原型对象,对原来的内置对象进行扩展自定义的方法。比如给数组增加自定义求偶数和的功能。(原型对象的应用)
Array.prototype.sum=function(){
var sum=0
for(i=0;i
注意
数组和字符串内置对象不能以对象的形式追加,因为会覆盖原本的内置方法——Array.prototype = {} ,只能使用Array.prototype.xxx = function(){} 的方式。
ES6之前并没有给我们提供extends继承。我们可以通过构造函数+原型对象模拟实现继承,被称为组合继承。
调用这个函数, 并且修改函数运行时的 this 指向
fun.call(thisArg, arg1, arg2, ...)
核心原理:
通过 call() 把父类型的 this 指向子类型的 this ,这样就可以实现子类型继承父类型的属性。
extends属于类的继承,写法是class Son extends Father。
这里是函数
super()是访问和调用父构造函数的方法
call()是继承父构造函数的类和方法
// 父类
function Father(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
// 子类
function Son(name, age, sex, score) {
Father.call(this, name, age, sex); // 此时父类的 this
指向子类的 this,同时调用这个函数
this.score = score;
}
var s1 = new Son('zs', 18, '男', 100);
console.dir(s1);
子类构造函数中通过call将父类构造函数this指向自身,达到继承父类属性目的
一般情况下,对象的方法都在构造函数的原型对象中设置,通过构造函数无法继承父类方法。
核心原理:
ES6之前通过 构造函数+ 原型实现面向对象 编程
ES6通过 类 实现面向对象编程
迭代(遍历)方法: forEach()、map()、filter()、some()、every();
array.forEach(function(value, index, array))
1. value每一个数组元素
2. index每一个数组元素的索引号
3. array数组本身
var arr = [1, 2, 3]
arr.forEach(function (value, index, array) {
console.log('每个数组元素' + value);
console.log('每个数组元素的索引号' + index);
console.log('数组本身' + array);
})
array.filter(function(value, index, array))
1. value每一个数组元素
2. index每一个数组元素的索引号
3. array数组本身
var arr = [12, 66, 4, 88, 3, 7];
//newAArr接收返回的数组
var newArr = arr.filter(function (value, index) {
// return value >= 20;
return value % 2 === 0;
});
console.log(newArr);
array.some(function(value, index, array))
1. value每一个数组元素
2. index每一个数组元素的索引号
3. array数组本身
some() 方法用于检测数组中的元素是否满足指定条件。即查找数组中是否有满足条件的元素。
注意它返回值是布尔值, 如果查找到这个元素, 就返回true, 如果查找不到就返回false。
如果找到第一个满足条件的元素,则终止循环,不在继续查找。
var arr = ['red', 'green', 'blue', 'pink'];
// 1. forEach迭代 遍历
arr.forEach(function(value) {
if (value == 'green') {
console.log('找到了该元素');
// return true; // 在forEach 里面 return 不会终止迭代
}
console.log(11);
})
// 如果查询数组中唯一的元素, 用some方法更合适,
arr.some(function (value) {
if (value == 'green') {
console.log('找到了该元素');
return true; // 在some 里面 遇到 return true
//就是终止遍历 迭代效率更高
}
console.log(11);
});
arr.filter(function (value) {
if (value == 'green') {
console.log('找到了该元素');
return true; // filter 里面 return 不会终止迭代
}
console.log(11);
});
用于获取对象自身所有的属性
Object.keys(对象参数名)
定义对象中新属性或修改原有的属性。(了解)
Object.defineProperty(obj, prop, descriptor)
以对象形式 { } 书写
// Object.defineProperty() 定义新属性或修改原有的属性
var obj = {
id: 1,
pname: '小米',
price: 1999
};
Object.defineProperty(obj, 'num', {
value: 1000,
enumerable: true
});
console.log(obj);
Object.defineProperty(obj, 'price', {
value: 9.9
});
console.log(obj);
Object.defineProperty(obj, 'id', {
// 如果值为false 不允许修改这个属性值 默认值也是false
writable: false,
});
obj.id = 2;
console.log(obj);
Object.defineProperty(obj, 'address', {
value: '中国山东蓝翔技校xx单元',
writable: false,
// enumerable 如果值为false 则不允许遍历, 默认的值是 false
enumerable: false,
// configurable 如果为false 则不允许删除这个属性
//不允许再修改第三个参数里面的特性 默认为false
configurable: false
});
console.log(obj);
console.log(Object.keys(obj));
delete obj.address;
console.log(obj);
delete obj.pname;
console.log(obj);
Object.defineProperty(obj, 'address', {
value: '中国山东蓝翔技校xx单元',
// 如果值为false 不允许修改这个属性值 默认值也是false
writable: true,
// enumerable 如果值为false 则不允许遍历, 默认的值是 false
enumerable: true,
// configurable 如果为false 则不允许删除以及这个属性
不允许再修改第三个参数里面的特性默认为false
configurable: true
});
console.log(obj.address);//不允许再修改第三个参数里面的特性
函数声明方式 function 关键字 (命名函数)
function fn(){};
函数表达式 (匿名函数)
var fun =function(){};
new Function()
var fn = new Function(‘参数1’,‘参数2’…, ‘函数体’)
普通函数
function fn() {
console.log(‘人生的巅峰’);
}
对象的方法
var o = {
sayHi: function() {
console.log(‘人生的巅峰’);
}
}
o.sayHi();
构造函数
function Star() {};
new Star();
绑定事件函数
btn.onclick = function() {}; // 点击了按钮就可以调用这个函数
定时器函数
setInterval(function() {}, 1000);
//这个函数是定时器自动1秒钟调用一次
立即执行函数
(function() {
console.log(‘人生的巅峰’);
})();
// 立即执行函数是自动调用
两种写法
( function () {} ) ()
( function () {} () )
调用方式的不同决定了this 的指向不同,一般指向调用者。
调用方式 | this指向 |
---|---|
普通函数调用 | window |
对象方法调用 | 对象 |
构造函数调用 | 实例对象;原型对象里的this也指向实例对象 |
绑定事件调用 | 绑定事件的对象 |
定时器函数调用 | window |
立即执行函数调用 | window |
常用的有 bind()、call()、apply() 三种方法。
call() 方法调用一个对象。简单理解为调用函数的方式,但是它可以改变函数的 this 指向。
fun.call(thisArg, arg1, arg2, ...)
apply() 方法调用一个函数。简单理解为调用函数的方式,但是它可以改变函数的 this 指向。
fun.apply(thisArg, [argsArray])
var arr = [1, 66, 3, 99, 4];
var arr1 = ['red', 'pink'];
var max = Math.max.apply(Math, arr);
var min = Math.min.apply(Math, arr);
console.log(max, min);
bind() 方法不会调用函数。但是能改变函数内部this指向。
fun.bind(thisArg, arg1, arg2, ...)
3. bind() 绑定 捆绑的意思
var o = {
name: 'andy'
};
function fn(a, b) {
console.log(this);
console.log(a + b);
};
var f = fn.bind(o, 1, 2);
f();
// 1. 不会调用原来的函数
可以改变原来函数内部的this 指向
// 2. 返回的是原函数改变this之后产生的新函数
// 3. 如果有的函数我们不需要立即调用,但是又想改变这个函数内部的this指向此时用bind
// 4. 我们有一个按钮,当我们点击了之后,就禁用这个按钮,3秒钟之后开启这个按钮
都可以改变this指向
JavaScript 除了提供正常模式外,还提供了严格模式(strict mode)。ES5 的严格模式是采用具有限制性 JavaScript 变体的一种方式,即在严格的条件下运行 JS 代码。
严格模式在 IE10以上版本的浏览器中才会被支持,旧版本浏览器中会被忽略。
严格模式对正常的 JavaScript 语义做了一些更改:
严格模式可以应用到整个脚本或个别函数中。因此在使用时,我们可以将严格模式分为为脚本开启严格模式和为函数开启严格模式两种情况。
为整个脚本文件开启严格模式,需要在所有语句之前放一个特定语句“use strict”;(或‘use strict’;)。
因为"use strict"加了引号,所以老版本的浏览器会把它当作一行普通字符串而忽略。
有的 script 基本是严格模式,有的script脚本是正常模式,这样不利于文件合并,所以可以将整个脚本文件放在一个立即执行的匿名函数之中。这样独立创建一个作用域而不影响其他 script 脚本文件。
要给某个函数开启严格模式,需要把“use strict”; (或 ‘use strict’; ) 声明放在函数体所有语句之前。
function fn(){
"use strict";
这里面的代码按照严格模式执行
}
function fun(){
这里面还是按照普通模式执行
}
更多严格模式要求参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Strict_mode
高阶函数是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出。
变量根据作用域的不同分为两种:全局变量和局部变量。
闭包(closure)指有权访问另一个函数作用域中变量的函数。
----- 《JavaScript 高级程序设计》
简单理解就是,一个作用域可以访问另外一个函数内部的局部变量。
提问:我们怎么能在fn()函数外面访问fn()中的局部变量 num 呢
闭包作用:延伸变量的作用范围。
内存泄漏:是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
JavaScript垃圾回收的机制很简单:标记清除找出不再使用的变量,然后释放掉其占用的内存,但是这个过程不是实时的,因为其开销比较大,所以垃圾回收器会按照固定的时间间隔周期性的执行。
Object.assign(target, ...sources)
属于es6 新增方法,可以浅拷贝。
这块的代码建议配合视频理解。
其余深拷贝操作可以参照以下链接的内容及其评论。
https://www.cnblogs.com/renbo/p/9563050.html
因之前接触过正则表达式,个人觉得用时百度就可以了,视频讲的内容理解就够了。
1. 灵活性、逻辑性和功能性非常的强。
2. 可以迅速地用极简单的方式达到字符串的复杂控制。
3. 对于刚接触的人来说,比较晦涩难懂。比如验证邮箱:
^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
4. 实际开发,一般都是直接复制写好的正则表达式。
但是要求会使用正则表达式并且根据实际情况修改正则
表达式。比如用户名: /^[a-z0-9_-]{3,16}$/
在 JavaScript 中,可以通过两种方式创建一个正则表达式。
1. 通过调用 RegExp 对象的构造函数创建
var 变量名 = new RegExp(/表达式/);
2. 通过字面量创建
var 变量名 = /表达式/;
以上 // 注释中间放表达式就是正则字面量,更推荐使用第二种
test() 正则对象方法,用于检测字符串是否符合该规则,该对象会返回 true 或 false,其参数是测试字符串。
regexObj.test(str)
regexObj 是写的正则表达式
str 我们要测试的文本
就是检测str文本是否符合我们写的正则表达式规范.
一个正则表达式可以由简单的字符构成,比如 /abc/,也可以是简单和特殊字符的组合,比如 /ab*c/ 。其中特殊字符也被称为元字符,在正则表达式中是具有特殊意义的专用符号,如 ^ 、$ 、+ 等。
特殊字符非常多,可以参考:
正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符。
边界符 | 说明 |
---|---|
^ | 表示匹配行首的文本(以谁开始) |
$ | 表示匹配行尾的文本(以谁结束) |
如果 ^ 和 $ 在一起,表示必须是精确匹配。
字符类表示有一系列字符可供选择,只要匹配其中一个就可以了。所有可供选择的字符都放在方括号内。
多选一
/[abc]/.test('andy') // true
字符串只要包含 abc 中任意一个字符都会返回 true 。
/^[abc]$/.test('andy') // true
三选一 只有是a 或者是 b 或者是c 这三个字母才返回 true
var reg = /^[a-z]$/; //
26个英文字母任何一个字母返回 true - 表示的是a 到z 的范围
方括号内部加上 - 表示范围,这里表示 a 到 z 26个英文字母都可以。
var reg = /^[a-zA-Z0-9_-]$/;
26个英文字母(大写和小写都可以)任何一个字母返回 true
如果中括号里面有^ 表示取反的意思 不要与 边界符 ^ 混淆
var reg = /^[^a-zA-Z0-9_-]$/;
量词符用来设定某个模式出现的次数。
header 1 | header 2 |
---|---|
* | 重复 0 次 或者 更多次 |
+ | 重复一次 或者 更多次 |
? | 重复 0 次 或 一次 |
{n} | 重复 n 次 |
{n,} | 重复 n 次 或者 更多次 |
{n,m} | 重复 n 次 到 m 次 |
符号 | 属性 | 意义 |
---|---|---|
大括号 | 量词符。 | 里面表示重复次数 |
中括号 | 字符集合。 | 匹配方括号中的任意字符. |
小括号 | 表示优先级。 |
中括号:字符集合。匹配方括号中的任意字符。
var reg = /^[abc]$/;
大括号:量词符。里面表示重复次数。
var reg = /^abc{3}$/;
小括号:表示优先级。
var reg = /^(abc){3}$/;
str.replace(regexp|substr, newSubStr|function)
参数 | 定义 |
---|---|
regexp (pattern) | 一个RegExp对象或者其字面量。该正则所匹配的内容会被第二个参数的返回值替换掉。 |
substr (pattern) | 一个将被 newSubStr替换的 字符串。其被视为一整个字符串,而不是一个正则表达式。仅第一个匹配项会被替换。 |
newSubStr (replacement) | 用于替换掉第一个参数在原字符串中的匹配部分的字符串。该字符串中可以内插一些特殊的变量名。参考下面的使用字符串作为参数。 |
function (replacement) | 一个用来创建新子字符串的函数,该函数的返回值将替换掉第一个参数匹配到的结果。 |
/表达式/[switch]
switch(也称修饰符):按照什么样的模式来匹配,有三种值:
g:全局匹配
i:忽略大小写
gi:全局匹配+忽略大小写
用多个敏感词使用 “ | ”
例如:/第一个|第二个/
let关键字就是用来声明变量的;
let a = 10;
console.log(a);// a is not defined
if (true) {
let b = 20;
console.log(b)
if (true) {
let c = 30;
}
console.log(c);
}
console.log(b)
if (true) {
let num = 100;
var abc = 200;
}
console.log(abc);
console.log(num)
for (let i = 0; i < 2; i++) {}
console.log(i)
console.log(a);
let a = 100;
var tmp = 123;
if (true) {
tmp = 'abc';
let tmp; //tmp is not defined
}
var arr = [];
for (var i = 0; i < 2; i++) {
arr[i] = function () {
console.log(i);
}
}
arr[0]();
arr[1]();
经典面试题图解:此题的关键点在于变量i是全局的,函数执
行时输出的都是全局作用域下的i值。
let arr = [];
for (let i = 0; i < 2; i++) {
arr[i] = function () {
console.log(i);
}
}
arr[0]();
arr[1]();
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WW4NxOdB-1599014955527)(https://github.com/BXsweetheart/youdaoNotes/blob/master/let%E9%9D%A2%E8%AF%95%E9%A2%98.png?raw=true)]
经典面试题图解:此题的关键点在于每次循环都会产生一个块
级作用域,每个块级作用域中的变量都是不同的,函数执行时
输出的是自己上一级(循环产生的块级作用域)作用域下的i
值.
作用:声明常量,常量就是值(内存地址)不能变化的量;
if (true) {
const a = 10;
}
console.log(a) // a is not defined
const PI; // Missing initializer in const declaration
const PI = 3.14;
PI = 100;
const ary = [100, 200];
ary[0] = 123;//(没有更改内存地址)数据可以更改
即数据结构内部的值可以更改
ary = [1, 2] //更改的是内存地址,所以数据值本身不可更改
console.log(ary);
var | let | const |
---|---|---|
函数级作用域 | 块级作用域 | 块级作用域 |
变量提升 | 不存在变量提升 | 不存在变量提升 |
只可更改 | 只可更改 | 值不可更改 |
ES6中允许从数组中提取值,按照对应位置,对变量赋值。对
象也可以实现解构。
允许我们按照一一对应的关系从数组中提取值,然后将值赋给变量
let [a, b, c] = [1, 2, 3];
console.log(a)
console.log(b)
console.log(c)
如果解构不成功,变量的值为undefined。
let [foo] = [];
let [bar, foo] = [1];
对象解构允许我们使用变量的名字匹配对象的属性,匹配成
功将对象属性的值赋给变量
let person = { name: 'zhangsan', age: 20 };
let { name, age } = person;
console.log(name); // 'zhangsan'
console.log(age); // 20
let {name: myName, age: myAge} = person; // myName myAge 属于别名
console.log(myName); // 'zhangsan'
console.log(myAge); // 20
ES6中新增的定义函数的方式,用来简化函数定义语法的。
书写格式 : () => {}
const fn = () => {
console.log(123)
}
fn()
函数体中只有一句代码,且代码的执行结果就是返回值,可
以省略大括号。
function sum(num1, num2) {
return num1 + num2;
}
const sum = (num1, num2) => num1 + num2;
const result=sum(10,20)
在箭头函数中,如果形参只有一个,形参外面的小括号也可以省略.
function fn (v) {
return v;
}
const fn = v => v;
箭头函数不绑定this关键字,箭头函数中的this,指向的是
函数定义位置的上下文this。
也就是说箭头函数被定义在哪里,箭头函数中的this就指向哪里。
const obj = { name: '张三'}
function fn () {
console.log(this);//指向obj
return () => {
console.log(this)
}
}
const resFn = fn.call(obj);
resFn();
var obj = {
age: 20,
say: () => {
alert(this.age)
}
}
obj.say();//会alert undefined 对象不能产生作用域
上方代码中对象不能产生作用域,所以此处的箭头函数被定
义在了全局 作用域下,此时的this指向的是window,window
下没有age属性,所以undefined。
var age=100
var obj = {
age: 20,
say: () => {
alert(this.age)
}
}
obj.say();//会alert undefined
剩余参数语法允许我们将一个不定数量的参数表示为一个数组。
function sum (first, ...args) {
console.log(first); // 10
console.log(args); // [20, 30]
}
sum(10, 20, 30)
const sum = (...args) => {
let total = 0;
args.forEach(item => total += item);
return total;
};
console.log(sum(10, 20));
console.log(sum(10, 20, 30));
let ary1 = ['张三' , '李四', '王五'];
let [s1, ...s2] = ary1;
console.log(s1)
console.log(s2)//...s2已经变成了一个数组,存储了"李四","王五"
扩展运算符可以将数组或者对象转为用逗号分隔的参数序列。
let ary = [1, 2, 3];
...ary // 1, 2, 3
console.log(...ary); // 1 2 3
console.log(1, 2, 3)
1. 扩展运算符可以应用于合并数组
// 方法一
let ary1 = [1, 2, 3];
let ary2 = [3, 4, 5];
let ary3 = [...ary1, ...ary2];
// 方法二
let ary1 = [1, 2, 3];
let ary2 = [4, 5, 6];
ary1.push(...ary2);
console.log(ary1)
2. 利用扩展运算符将伪数组或者可遍历对象转换为真正的数组
var oDivs = document.getElementsByTagName('div');
console.log(oDivs)
var ary = [...oDivs];
ary.push('a');
console.log(ary);
1. 将类数组或可遍历对象转换为真正的数组
2. 该方法还可以接受第二个参数,作用类似于数组的map方
法,用来对每个元素进行处理,将处理后的值放入返回的
数组。
var arrayLike = {
"0": "张三",
"1": "李四",
"2": "王五",
"length": 3
}
var ary = Array.from(arrayLike);
console.log(ary)
var arrayLike = {
"0": "1",
"1": "2",
"length": 2
}
var ary = Array.from(arrayLike, item => item * 2)
console.log(ary)//输出处理后的结果。
用于找出第一个符合条件的数组成员,它的参数是一个回调
函数,所有数组成员依次执行该回调函数,直到找出第一个
返回值为true的成员,然后返回该成员。如果没有找到返回
undefined
var ary = [{
id: 1,
name: '张三'
}, {
id: 2,
name: '李四'
}];
let target = ary.find(item => item.id == 3);
console.log(target)//返回undefined
返回第一个符合条件的数组成员的位置,如果所有成员都不
符合条件,则返回-1。
let ary = [1, 5, 10, 15];
let index = ary.findIndex((value, index) => value > 9);
console.log(index); // 2(第一个符合条件的索引,即10的索引是2)
判断某个数组是否包含给定的值,返回布尔值
[1, 2, 3].includes(2) // true
[1, 2, 3].includes(4) // false
该方法的第二个参数表示搜索的起始位置,默认为0。如果第
二个参数为负数,则表示倒数(shu)的位置,如果这时它大于数组
长度(比如第二个参数为-4,但数组长度为3),则会重置为
从0开始。
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
ES6新增的创建字符串的方式,使用反引号定义。
1. 模板字符串中可以解析变量;
2. 模板字符串中可以换行;
3. 在模板字符串中可以调用函数。
let name = `张三`;
console.log(name)
let sayHello = `Hello, 我的名字叫${name}`;
console.log(sayHello);
// let html = `
${result.name}
${result.age}
`;
console.log(html);
const fn = () => {
return '我是fn函数'
}
const fn = () => {
return '我是fn函数'
}
let html = `我是模板字符串 ${fn()}`;
console.log(html)
includes():返回布尔值,表示是否找到了参数字符串;
startsWith():表示参数字符串是否在原字符串的头部,返回布尔值;
endsWith():表示参数字符串是否在原字符串的尾部,返回布尔值。
这三个方法都支持第二个参数,表示开始搜索的位置。
let str = 'Hello ECMAScript 2015';
let r1 = str.startsWith('Hello');
console.log(r1);// true
let r2 = str.endsWith('2015');
console.log(r2);// true
let r2 = str.endsWith('2016');
console.log(r2) //false
repeat方法表示将原字符串重复n次,返回一个新字符串。
ES6 提供了新的数据结构——Set。
1. 它类似于数组,但是成员的值都是唯一的,没有重复的值。
2. Set本身是一个构造函数,用来生成 Set 数据结构。
3. Set函数可以接受一个数组作为参数,用来初始化。
4. Set可以去除数组重复元素。
const s1 = new Set();
console.log(s1.size)//返回0
const s2 = new Set(["a", "b"]);
console.log(s2.size)//返回2
const s3 = new Set(["a","a","b","b"]);
console.log(s3.size)//返回2
const ary = [...s3];
console.log(ary)//数组中存储了["a","b"]
const s4 = new Set();
s4.add('a').add('b');//链式调用
console.log(s4.size)
const r1 = s4.delete('c');
console.log(s4.size)
console.log(r1);
const r2 = s4.has('d');
console.log(r2)
s4.clear();
console.log(s4.size);
Set 结构的实例与数组一样,也拥有forEach方法,用于对每
个成员执行某种操作,没有返回值。
// 遍历set数据结构 从中取值
const s5 = new Set(['a', 'b', 'c']);
s5.forEach(value => {
console.log(value)
})
### 正则表达式
18位身份证号
/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}[0-9Xx]$/;