JavaScript复习二

本文从DOM开始,复习了DOM BOM JS高级语法 JSON AJAX Cookie 闭包,到ES6新特性 解构赋值 模板字符串 箭头函数 rest参数 生成器 迭代器 Promise set Map 深拷贝与浅拷贝。完成了js的复习,方便后续的学习。
本文参考神仙博主:轻松的小希的博客

文章目录


前言

1、DOM元素节点增删改查

1.1 获取DOM元素

  1. document.getElementById(‘xx’);
  2. document.getElementsByTagName(‘xxx’);
  3. document.getElementsByClassName(‘xxx’);
  4. document.querySelector(‘button’);表示根据元素名称选择
  5. document.querySelector(‘.btn’);表示根据类名选择
  6. document.querySelector(‘#nav’);表示根据id选择
  7. document.querySelectorAll();表示选出所有名为xx的元素

1.2 修改DOM元素(增删改查)

1.2.1 创建HTML元素

  1. var li1 = document.createElement(‘li’);创建元素节点
  2. document.createAttribute(‘src’);创建属性节点
  3. var text1 = document.createTextNode('你好啊,我是1号’);创建文本节点,然后添加到元素节点li1中 li1.appendChild(text1);
    文本节点也可以使用 li1.innerHTML = ‘你好啊,我是1号’;

1.2.2 在父元素中追加元素appendChild();

  1. ul.appendChild(li1); 将节点追加到元素后面。 li1是已经创建了的元素节点
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

<!-- 在这里写JavaScript代码,因为JavaScript是由上到下执行的 -->
<script>
    var ul = document.createElement("ul");

    var li1 = document.createElement("li");
    var text1 = document.createTextNode("列表项1");
    li1.appendChild(text1);
    ul.appendChild(li1);

    var li2 = document.createElement("li");
    // var text2 = document.createTextNode("列表项2");
    // li2.appendChild(text2);
    li2.innerHTML = "列表项2";
    ul.appendChild(li2);

    var li3 = document.createElement("li");
    // var text3 = document.createTextNode("列表项3");
    // li3.appendChild(text3);
    li3.innerHTML = "列表项3";
    ul.appendChild(li3);

    var li4 = document.createElement("li");
    var text4 = document.createTextNode("列表项4");
    li4.appendChild(text4);
    ul.appendChild(li4);

    document.getElementsByTagName("body")[0].appendChild(ul);
</script>
</body>
</html>

1.2.3 在某位置之前插入 替换元素节点 删除节点

  1. ul.insertBefore(插入的元素节点,插入的位置)在待插入位置之前插入元素节点
  2. ul.moveChild(待删除的元素节点);
  3. ul.replaceChild(准备插入的节点,被换下去的节点)
<script>
	// 创建元素节点,配上文本节点,并追加到父节点中
	var ul = document.createElement('ul');
	
	var li1 = document.createElement('li');
	var text1 = document.createElement('你好,我是1号');
	li1.appendChild(text1);

	var li2 = document.createElement('li');
	li2.innerHTML = '你好,我是2号';
	li2.appendChild(ul);

	document.getElementByTagName('body')[0].appendChild(ul);

	// 创建一个元素节点,插到指定节点的前面
	var zero = document.createElement('li');
	zero.innerHTML = '哈哈哈,我是插入过来的0号元素';
	ul.insertBefore(zero,li1);

	// 删除li1节点
	ul.removeChild(li1);

	// 把最后一个节点替换成replaceLi
	var replaceLi = document.createElement('li');
	replaceLi.innerHTML = '我是来把最后一个换下去的';
	ul.replaceChild(replaceLi,li2);
	
</script>

1.3 获取与修改元素的值

1.3.1 获取元素的值

  1. 获取文本:box.innerHTML; box.innerText。如<div> <a href="www.baidu.com">百度一下你就知道</div>,使用div.innerHTML()可以得到a链接和文字;使用innerText()只能得到文本。区别如下:innerHTML获取从对象的起始位置到终止位置的全部内容,包括Html标签;innerText获取从起始位置到终止位置的内容,但它去除Html标签。
  2. 获取属性:a.href;a.getAttribute(‘href’);
  3. 获取元素样式:如宽 高 背景色 文本大小等css样式:box.style.width
    元素样式中要注意采用小驼峰如 box.style.backgroundColor;

1.3.2 修改元素的值

  1. 修改文本:
box.innerText = 'hello world';
box.innerHTML = '<a>你好啊世界</a>';//可以写入标签
  1. 修改属性:
a.href="https://www.jd.com";
a.setAttribute('href','https://www.jd.com');
  1. 修改style样式: box.style.backgroundColor = ‘green’;

1.4 获取父/子/兄弟元素(不包含空节点)

1.4.1 父元素

	 box.parentElement 
	 box.parentNode

1.4.2 子元素

  1. var lists = ul.children
  2. var first = ul.firstElementChild;
  3. var last = ul.lastElementChild;

1.4.3 兄弟元素

  1. var pre = two.previousElementSibling;
  2. var next = two.nextElementSibling;

2、DOM事件方法

2.1 窗口事件

获取焦点时onfocus、失去焦点时onblur、加载完成时onload、窗口大小变化onresize时、存储空间中的数据发生变化时 onstorage

<script>

	window.onblur = function (){
		alert('窗口失去焦点了');
	}
	window.onfocus = function (){
		alert('窗口获取焦点了');
	}

	window.onload = function (){
		alert('窗口加载完成了');
	}

	window.onresize = function (){
		alert('窗口大小正在改变');
	}

</script>

2.2 表单事件

  1. onblur onfocus onsubmit(form使用) oninvalid onselect
  2. onchange(当元素内容改变时) 当文本框内容改变时,鼠标离开文本框,自动将文本框的内容输出到控制台。只会输出鼠标离开文本框时的内容
  3. oninput(当元素获得用户输入时)当文本框内容改变时,立即将改变的内容输出到控制台。会将变化的过程展示出来

2.3 键盘事件

  1. onkeyup onkeydown onkeypress
  2. 写一个程序,让div盒子在页面移动
  3. box.offsetTop box.offsetLeft 盒子距离页面左侧和上侧的位置
  4. e.clientX e.clientY鼠标指针的水平垂直位置
<script>
// 必须给box加绝对定位才能获取到offsetLeft offsetTop,且这两个没有单位。left top才有单位
    var box = document.querySelector('.box');
    document.addEventListener('keydown', function(event) {
        var speed = 10;
        switch (event.keyCode) {
            case 39:
                box.style.left = box.offsetLeft + speed + 'px';
                break;
            case 37:
                box.style.left = box.offsetLeft - speed + 'px';
                break;
            case 40:
                box.style.top = box.offsetTop + speed + 'px';
                break;
            case 38:
                box.style.top = box.offsetTop - speed + 'px';
                break;
            default:
                console.log('sorry,请按下移动键');
                break;
        }
    })
</script>

2.4 鼠标事件

  1. 点击:onclick ondblclick
  2. 按下弹起移动:onmousedown onmouseup onmousemove
  3. 鼠标放到某个元素身上(可以冒泡):onmouseover onmouseout
  4. 鼠标放到某个元素身上(不能冒泡):onmouseenter onmouseleave
  5. 鼠标滚轮滚动:onmousewheel
  6. 元素滚动条滚动:onscroll
    进行一个拖拽事件实例
    必须使用绝对定位
<script>
    var box = document.querySelector('.box');
    box.onmousedown = function(e) {
        var x = e.clientX - box.offsetLeft;
        var y = e.clientY - box.offsetTop;

        document.onmousemove = function(e) {
            box.style.left = e.clientX - x + 'px';
            box.style.top = e.clientY - y + 'px';
        }
        document.onmouseup = function(e) {
            document.onmousemove = null;
            document.onmouseup = null;
        }
    }
</script>

2.5 事件冒泡捕获 阻止默认事件

事件冒泡:box.addEventListener(‘click’,function(){},false);侦听事件的第三个参数默认是false,表示冒泡;如果设为true,则为事件捕获

2.5.1 事件冒泡

  1. 冒泡事件:从里往外冒
  2. 阻止事件冒泡:事件执行时加上,event.stopPropagation();

2.5.2 事件捕获

  1. 事件侦听的第三个参数默认是false,因此当使用事件捕获时,需要手动改成true
  2. 事件捕获是从外往里捕

2.5.3 阻止默认行为

  1. e.preventDefault();

2.5.4 事件解绑

  1. 传统onclick事件解绑:btn.onclick = null;
btn.onclick=function(e){
	concole.log(e.target);
	btn.onclick=null;
}
  1. 侦听事件解绑:把函数写在外部
btn.addEventListener('click',fun);
function fun(){
	alert('11');
	btn.removeEventListener('click',fun);
}

3、BOM浏览器对象方法

BOM浏览器对象分为以下几类:
Window:代表的是整个浏览器的窗口,同时window也是网页中的全局对象
Navigator:代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器
Location:代表当前浏览器的地址栏信息,通过Location可以获取地址栏信息,或者操作浏览器跳转页面
History:代表浏览器的历史记录,可以通过该对象来操作浏览器的历史记录,由于隐私原因,该对象不能获取到具体的历史记录,只能操作浏览器向前或向后翻页,而且该操作只在当次访问时有效
Screen:代表用户的屏幕的信息,通过该对象可以获取到用户的显示器的相关的信息
这些BOM对象在浏览器中都是作为window对象的属性保存的,可以通过window对象来使用,也可以直接使用

3.1 Window对象

3.1.1 弹出框

分为alert confirm prompt三种,全写为window.alert window.confirm window.prompt,可以省略window

  1. alert()点击确定来继续
  2. confirm()点击确认时返回true,点击取消时返回false
  3. prompt()点击确认时返回输入框中的值,点击取消时返回null

3.1.2 定时事件

有两个方法
setTimeOut(function,seconds);表示等待多少毫秒执行
setInterval(function,seconds);表示隔几毫秒循环执行

3.1.3 语法

// 定义一个定时器
var timer = setTimeOut(function(){
	console.log('hello');
},3000);
// 删除一个定时器
clearTimeOut(timer);

var timer2 = setInterval(function(){
	console.log('我来啦');
},200);
clearInterval(timer2);

3.1.4 小车移动案例

xxx

3.2 Navigator对象

Navigator代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器。
使用Navigator.uerAgent实现对浏览器类型的判断

3.3 Location对象

3.3.1 location属性

  1. 封装了浏览器的地址栏的信息,如果直接打印location,则可以获取到地址栏的信息(当前页面的完整路径)
  2. console.log(location); //输出location对象
  3. console.log(location.href); //输出当前地址的全路径地址
  4. console.log(location.host); //输出当前地址的主机
  5. console.log(location.port); //输出当前地址的端口号
  6. location.href = “https://www.baidu.com”; //修改地址

3.3.2 location方法

  1. assign():用来跳转到其它的页面:location.assign(“https://www.baidu.com”);

  2. reload():用于重新加载当前页面,作用和刷新按钮一样,true表示强制清空缓存刷新页面:location.reload(true);

  3. replace():可以使用一个新的页面替换当前页面,调用完毕也会跳转页面,它不会生成历史记录,不能使用回退按钮回退:location.replace(“https://www.baidu.com”);

3.4 History对象

操作浏览器向前或向后翻页
属性:

  1. console.log(history); //输出history对象
  2. console.log(history.length); //可以获取到当成访问的链接数量
    方法:
  3. back():可以回退到上一个页面,作用和浏览器的回退按钮一样
 history.back();
  1. forward():可以跳转到下一个页面,作用和浏览器的前进按钮一样
history.forward();
  1. go(-2):跳转到指定的页面,整数表示向前跳转,负数表示向后跳转

3.5 Screen对象

4、JS高级语法

包含exception JSON AJAX cookie webStorage Closure

4.1 Exception异常

  1. JS内置error对象有两个属性:name message
  2. 异常捕获语法:
    (1)当try语句块中有错误时,就会执行catch中的语句;当try中没有错误时,catch中的语句不执行
    (2)finally中的语句无论是否发生错误都会执行
try{

}catch(error){

}finally{

}
  1. 错误类型:
    (1)SyntaxError:语法错误,少引号等
    (2)RangeError:范围错误
    (3)ReferenceError:引用错误,使用(引用)了尚未声明的变量,会被抛出
    (4)TypeError :类型错误,使用的值不在期望值的范围之内,则 被抛出
    (5) URIError:URI 函数中使用非法字符,被抛出
  2. 抛出异常throw new xxx()
    只要有异常对象抛出,不管是浏览器抛出的,还是代码主动抛出,都会让程序停止执行。如果想让程序继续执行,则有也可以用try…catch来捕获
    (1)抛出内置错误 throw new TypeError(‘我是类型错误’)
    (2)抛出自定义错误
/*自定义错误*/
function MyError(message) {
    this.message = "注意:这是自定义的错误"
    this.name = "自定义错误";
}
MyError.prototype = new Error();

try {
    throw new MyError("注意:这是自定义错误类型")
} catch (error) {
    console.log(error.message)
}

4.2 JSON

  1. 数据项:每一个数据项由键值对组成。键必须是使用双引号包起来的字符串;值是数字 字符串 null 对象(JSON对象 双引号引起来) 数组 布尔,不能是undefined 函数 日期
var person = {"name": "zhangsan", "age": 62, "city": "BeiJing"};
console.log(person);
  1. 值的类型:数字 布尔 null 数组 对象 字符串(JSON)
    (1)数字:整数或浮点数
    (2)字符串:必须用引号包起来,和键一样
    (3)对象:对象是key value组成的,因此对象是值时key和value也必须符合JSON要求,用双引号包起来
{
	"xiaoming":{"age":20,"height":"182cm","hobby":["games","eating","drinking"]}
}

(4)数组:{
“employees”: [“Bill”, “Steve”, “David”]
}
(5)null:{“middlename”: null}
(6)布尔:{“sale”: true}

  1. JSON字符串转为对象 JSON.parse(jsonStr);
var jsonStr = '{"name":"孙悟空","age":18,"gender":"男"}';
var obj = JSON.parse(jsonStr);
console.log(obj);
  1. JSON对象转为JSON字符串 JSON.stringify(jsonObj);
var obj = {name: "猪八戒", age: 28, gender: "男"};
var jsonStr = JSON.stringify(obj);
console.log(jsonStr);

4.3 AJAX

用于创建快速动态网页的技术,通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新,这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新

4.3.1 AJAX的XMLHttpRequest对象

用于幕后同服务器交换数据

  1. 创建XMLHttpRequest
variable = new XMLHttpRequest();
  1. XMLHttpRequest对象的方法
    (1)open(“methods”,“url”,async)
    method表示请求类型get/post;url表示文件的位置;async表示true异步或false同步
    (2)send()发送get请求;send(string)发生post请求
    (3)setRequestHeader() 向要发送的报头添加标签/值对
    (4)getAllResponseHeaders() 返回头部信息
    (5)getResponseHeader() 返回特定的头部信息
    (6)abort() 取消当前请求
  2. XMLHttpRequest对象的属性
    (1)onreadystatechange:当readystate改变时,触发它定义的函数
ajax.onreadystatechange = function () {
    if (ajax.readyState == 4 && ajax.status == 200) {
        //步骤五:如果能够进到这个判断,说明数据完美的回来了,并且请求的页面是存在的
        console.log(ajax.responseText);//输入响应的内容
    }
};

(2)readyState:保存 XMLHttpRequest 的状态
0:请求未初始化
1:服务器连接已建立
2:请求已收到
3:正在处理请求
4:请求已完成且响应已就绪
(3)status:返回请求的状态号
200: “OK”
403: “Forbidden”
404: “Not Found”
(4)responseXML responseText:以XML 字符串形式返回响应数据
(5)statusText:返回状态文本

在这里插入代码片

4.3.2 get post请求

get请求

//步骤一:创建异步对象
var ajax = new XMLHttpRequest();
//步骤二:设置请求的url参数,参数一是请求的类型,参数二是请求的url
ajax.open("get", "users.json");
//步骤三:发送请求
ajax.send();
//步骤四:注册事件 onreadystatechange 状态改变就会调用
ajax.onreadystatechange = function () {
    if (ajax.readyState == 4 && ajax.status == 200) {
        //步骤五:如果能够进到这个判断,说明数据完美的回来了,并且请求的页面是存在的
        console.log(ajax.responseText);//输入响应的内容
    }
};

post请求

//步骤一:创建异步对象
var ajax = new XMLHttpRequest();
//步骤二:设置请求的类型及url,注意:post请求一定要添加请求头才行不然会报错
ajax.open("post", "users.json");
ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
//步骤三:发送请求
ajax.send();
//步骤四:注册事件 onreadystatechange 状态改变就会调用
ajax.onreadystatechange = function () {
    //步骤五:如果能够进到这个判断,说明数据完美的回来了,并且请求的页面是存在的
    if (ajax.readyState == 4 && ajax.status == 200) {
        console.log(ajax.responseText);//输入响应的内容
    }
};

综合:

var Ajax = {
    get: function (url, fn) {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', url, true);
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4 && xhr.status == 200 || xhr.status == 304) {
                fn.call(this, xhr.responseText);
            }
        };
        xhr.send();
    },
    post: function (url, data, fn) {
        var xhr = new XMLHttpRequest();
        xhr.open("POST", url, true);
        xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) {
                fn.call(this, xhr.responseText);
            }
        };
        xhr.send(data);
    }
};

// 演示GET请求
Ajax.get("users.json", function (response) {
    console.log(response);
});

// 演示POST请求
Ajax.post("users.json", "", function (response) {
    console.log(response);
});

4.4 cookie

记录客户端的用户信息,用户访问 web 页面时,它的名字可以记录在 cookie 中,用户下一次访问该页面时,可以在 cookie 中读取用户访问记录。

  1. 存储:以名=值形式:username=zhangsan
  2. 创建 cookie:document.cookie = "username=zhangsan";
  3. 读取 cookie:document.cookie 将以字符串的方式返回所有的 cookie,类型格式: cookie1=value; cookie2=value; cookie3=value
  4. 修改 document.cookie=‘xx’
  5. 删除 cookie 非常简单,您只需要设置 expires 参数为以前的时间即可
document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 GMT";

4.5 webStorage

分为两种: sessionStorage 和localStorage,只能存储字符串类型
sessionStorage:数据保存在session中,一旦浏览器窗口或标签页被永久关闭了,那么所有通过sessionStorage存储的数据也就被清空了
localStorage:数据保存在本地客户端,本地永久性存储数据,除非显式将其删除或清空

4.5.1 相关API

  1. localStorage相关API
    保存单个数据:localStorage.setItem(key,value);
    读取单个数据:localStorage.getItem(key);
    删除单个数据:localStorage.removeItem(key);
    删除所有数据:localStorage.clear();
    获取某个索引的key:localStorage.key(index);
    var key = localStorage.key(i); //键名
    var value = localStorage.getItem(key); //键值
    console.log(key + “=” + value);

4.6 闭包closure

4.6.1 闭包概念

  1. 产生:当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量(函数)时,就产生了闭包
  2. 是什么:闭包是嵌套的内部函数;包含被引用变量(函数)的对象
  3. 闭包作用:可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中

4.6.2 闭包生命周期

  1. 每次外部函数执行的时候,都会开辟一块内存空间,外部函数的地址不同,都会重新创建一个新的地址
  2. 产生:在嵌套内部函数定义执行完时就产生了(不是在调用)
  3. 死亡:在嵌套的内部函数成为垃圾对象时

4.6.3 常见闭包

  1. 返回内部函数
  2. 函数作为参数

4.6.4 闭包作用

  1. 函数内部的变量在函数执行完后,仍然存活在内存中(延长了局部变量的生命周期
  2. 让函数外部可以操作(读写)到函数内部的数据(变量/函数)

4.6.5 闭包缺点

  1. 函数执行完后,函数内的局部变量没有释放,占用内存时间会变长
  2. 容易造成内存泄漏

5、ES6

5.1 let const

  1. 块级作用域,不存在变量提升,不能重复声明
    const:不允许修改值,必须赋初始值
  2. const:对于数组和对象的元素修改, 不算做对常量的修改, 不会报错
  3. 引用类型的数据保存在堆中,栈中保存的是引用数据的指针,const保证指针指向不变即可,至于堆中的数据或属性可以改变,arr1=arr2不可以,这样改变了指针指向
  4. 引用数据用const声明,基本类型用let声明

5.2 解构赋值

  1. 数组解构赋值:以索引值下标为准,可以使用空格占位
const arr = ["张学友", "刘德华", "黎明", "郭富城"];
let [zhang, liu, li, guo] = arr;
  1. 对象解构赋值:以属性名为准,即使属性名顺序和对象不一致也没关系
const lin = {
    name: "林志颖",
    tags: ["车手", "歌手", "小旋风", "演员"]
};
let {name, tags} = lin;
  1. 复杂对象解构赋值:层层解开,使用:{ }形式
let wangfei = {
    name: "王菲",
    age: 18,
    songs: ["红豆", "流年", "暧昧"],
    history: [
        {name: "窦唯"},
        {name: "李亚鹏"},
        {name: "谢霆锋"}
    ]
};
let {name, age, songs: [one, two, three], history: [first, second, third]} = wangfei;

5.3 模板字符串 ``

(1)使用反引号包起来
(2)可以使用${name}拼接字符串和变量

let name = '小可爱';
let result = `欢迎${name}访问我的文章`;

5.4 对象的简化写法

当属性名和函数名一致时,可以简写一个

5.5 箭头函数

function fn=()=>{ }

  1. 写法简单
    (1)没有参数时写一个空括号
    (2)只有一个参数时,省略括号
    (3)多个参数时,用,分开
    (4)返回值只有一句时,省略大括号
    (5)没有return 仅调用函数时,使用void void Fun()

  2. this指向
    (1)箭头函数没有自己的this,它在定义时,根据上下文的环境,确定自己的this
    (2)此后this指向不更改,call apply bind都不会更改

  3. 不能作为构造函数

5.6 rest参数与spread拓展运算符

5.6.1 rest参数

(1)是一个数组,用来接收实参,使用…args,代替arguments数组
(2)要把rest参数放在形参的最后一个,如function fun(a,b,…args)

5.6.2 spread拓展运算符

(1)用来把数组解包为逗号分割的序列
(2)把数组解包当作实参 fun(…arr);

5.7 Symbol类型

  1. 基本数据类型,表示独一无二的值
    (1)Symbol的值是唯一的,解决命名冲突
    (2)Symbol不能和其他类型的数据运算
    (3)Symbol 定义的对象属性不能使用 for…in 循环遍 历

  2. 基本使用:

var s = new Symbol();

var s2 = new Symbol('张三');
var s2_2 =new Symbol('张三');
console.log(s2===s2_2);   //false

var s3 = new Sybmol.for('lili');
var s3_3 = new Symbol.for('lili');
console.log(s3===s3_3);   //true

//在对象的方法中使用Symbol对象 [Symbol('xx')]
//在方法中使用 Symbol
let game = {
    name: "狼人杀",
    [Symbol('say')]: function () {
        console.log("我可以发言")
    },
    [Symbol('zibao')]: function () {
        console.log('我可以自爆');
    }
};

5.8 迭代器

自定义遍历数据

5.8.1 具备接口的原生数据类型

Array
Arguments
Set
Map
String
TypedArray
NodeList

5.8.2 迭代器工作原理

创建一个指针,指向数据初始位置
第一次调用next(),指针指向数据结构的第一个成员
以后每次调用next(),指针向后移动一位
每次next()返回一个对象,包含value done两个属性

5.8.3 迭代器自定义遍历数据

获取迭代器对象 var iterator = objSymbol(iterator);

const o = {
            grade: "9",
            stus: [{
                name: 'x',
                age: 18
            }, {
                name: 'y',
                age: 22
            }, {
                name: 'z',
                age: 20
            }],
            [Symbol.iterator]() {
                let that = this;
                let index = 0;
                return {
                    next: function() {
                        if (index < that.stus.length) {
                            const stuObj = {
                                value: that.stus[index],
                                done: false
                            }
                            index++;
                            return stuObj;
                        } else {
                            return {
                                value: undefined,
                                done: true
                            }
                        }
                    }
                }
            }
        }

        for (let i of o) {
            console.log(i);
        }

5.9 生成器

5.9.1 概念

  1. 生成器:使用 function* 语法和一个或多个 yield 表达式以创建一个函数即为生成器
  2. 语法: function *gen(){ }
  3. 执行过程:
    (1)是可以暂停执行的,异步需要暂停的地方使用yield
    (2)调用生成器函数会返回一个指针 var g = gen();
    (3)调用指针 g 的 next 方法,会移动内部指针(即执行异步任务的第一段),指向第一个遇到的 yield 语句
    (4)再次调用g的next的方法,内部指针指向下个yield语句
    (5)next方法的返回值中的value就是yield中的语句,done表示是否遍历完成
  4. 生成器 迭代器 next方法
    next 方法的作用是分阶段执行生成器 函数。每次调用 next 方法,会返回一个对象,这个对象就是具有两个属性的迭代器对象。该对象有两个属性:value和done。 value 属性是 yield 语句后面表达式的值,表示当前阶段的值;done 属性是一个布尔值,表示生成器函数是否执行完毕

5.9.2 生成器委托

使用yield * 生成器名,将当前生成器委托到下一个生成器运行

function* stringIter() {
    var str = "bobsyouruncle";
    var idx = 0;
    while(idx < str.length)
        yield str[idx++];
}
function* strIter() {
    yield "jo";
    yield* stringIter();
}

var si2 = strIter();

console.log(si2.next().value);
console.log(si2.next().value);
console.log(si2.next().value);
console.log(si2.next().value);
输出:
jo
b
o
b

5.9.3 next带参数

生成高级别的生成器,以下案例中,index会被重新设定为0

function * strIter2() {
     var  str =  "jobob" ;
     var  idx = 0;
     while (idx < str.length) {
         var  modify = yield str[idx++];
         if (modify == 100) {
             idx = 0;
         }
     }
 
}
 
var  str2 =  strIter2();
 
console.log(str2.next().value);
console.log(str2.next().value);
console.log(str2.next().value);

console.log(str2.next(100).value);
输出:

j

o

b

j

5.10 Promise

有两个回调,成功的和失败的

5.10.1 基本概念

  1. promise实例化
const p = new Promise(function(resolve,reject){
	resolve('xx');
	reject('yy');
});
//回调函数,一个成功的回调和一个失败的回调
const pp = new Promise((resolve,reject)=>{
	resolve();
	reject();
});
  1. promise的then方法
p.then(function(resolve){
	console.log('xxx');
},function(reject){
	console.error('xxxx');
});
p.then(resolve=>{

},reject=>{

})

5.11 Set Map

使用set()创建一个集合,类似数组,但是set的元素的数据类型是统一的,且不存在相同的值,有iterator接口

  1. set的属性和方法
    (1)使用new Set创建一个集合 var s1 = new Set(); var s2 = new Set([1,2,3]);
    (2)返回集合中元素个数,相同的元素只记1次 s1.size
    (3)添加元素,返回集合 s1.add(4);
    (4)删除元素,返回布尔 s1.delete(8);
    (5)判断是否含有某个元素,返回布尔 s1.has(4);
    (6)清空集合,返回undefined s1.clear();

使用map()创建一个集合,类似对象,是键值对的集合,但是键名必须用“”包起来,键名不止是字符串,可以是对象数组等,有iterator接口

  1. map属性和方法
    (1)使用new Map创建一个集合 var m = new Map();
    (2)返回集合元素个数,m.size
    (3)添加元素,返回集合 m.set(“键名”,“键值”);
    (4)返回键名对应的键值 m.get(“键名”);
    (5)清空集合,返回undefined m.clear();

5.12 数值拓展

  1. 方法
    (1)Number.EPSILON是最小精度,当两数之差小于最小精度,即可认定两者相等
    (2)Number.isFinite(xx)检测一个数是否无穷
    (3)Number.isNaN(xx)检测一个数是否为NaN,当参数不是Number型时,直接返回false
    (4)Number.parseInt(xx):将一个字符串转换为整数
    (5)Number.parseFloat(xx):将一个字符串转换为浮点数
    (6)Number.isInteger(xx):判断一个数是否为整数
    (7)Math.trunc(xx):将数字的小数部分抹掉
    (8)Math.sign(xx):判断一个数到底为正数1、负数-1、还是零0

5.13 对象拓展

5.13.1 Object.is(x,y)判断两个对象相等

  1. Object.is:判断两个值是否完全相等
  2. 与===的区别:NaN和+0 -0
    (1)Object.is(NaN,NaN) true
    (2)console.log(NaN ===NaN) false

5.13.2 Object.assign(obj1,obj2)对象的合并

把obj2的属性和值复制到obj1中,如果有冲突的值则obj1被覆盖掉

5.13.3 Object设置原型对象__proto__

  1. 设置原型方法:Object.setPropertyOf(obj,p) 给obj的__proto__上设置proto,并返回对象
function set(obj,proto){
	obj.__proto=proto;
	return obj;
}
  1. 获取原型方法:Object.getPropertyOf(proto)

5.14 模块化

  1. 暴露export
    (1)分别暴露
    export let a=1;
    export var obj={name:‘小明’,age:20}
    (2)统一暴露
    export {a, obj}
    (3)默认暴露
    export default a=1
  2. 引入
    import a from ‘’./test.js"

5.15 深拷贝与浅拷贝

5.15.1 浅拷贝

把obj1的值赋给obj2,当obj1改变时,如果obj2也改变,则为浅拷贝

var obj1 = {
    name: "张三",
    age: 20,
    speak: function () {
        console.log("我是" + this.name);
    }
};

var obj2 = obj1;

// 当修改obj2的属性和方法的时候,obj1相应的属性和方法也会改变
obj2.name = "李四";
console.log(obj1);
console.log(obj2);

5.15.2 深拷贝

5.15.2.1数组自带的深拷贝

slice() concat() Array.from() … 只能拷贝一维数组

  1. var arr2 = arr1.slice()
var arr1 = [1, 2, 3, 4];
var arr2 = arr1.slice();
arr2[0] = 200;
console.log(arr1); //[1,2,3,4]
console.log(arr2); //[200,2,3,4]
  1. var arr3 = arr1.concat()
var arr1 = [1, 2, 3, 4];
var arr2 = arr1.concat();
arr2[0] = 200;
console.log(arr1); //[1,2,3,4]
console.log(arr2); //[200,2,3,4]

  1. Array.from()
var arr1 = [1, 2, 3, 4];
var arr2 = Array.from(arr1);
arr2[0] = 200;
console.log(arr1); //[1,2,3,4]
console.log(arr2); //[200,2,3,4]

  1. …拓展运算符
var arr1 = [1, 2, 3, 4];
var arr2 = [...arr1];
arr2[0] = 200;
console.log(arr1); //[1,2,3,4]
console.log(arr2); //[200,2,3,4]
5.15.2.2 对象自带的深拷贝

Object.assign() …只能实现一维对象的深拷贝

  1. var obj2 = Object.assign({ },obj1)
var obj1 = {
    name: "张三",
    age: 20,
    speak: function () {
        console.log("我是" + this.name);
    }
};

var obj2 = Object.assign({}, obj1);

// 当修改obj2的属性和方法的时候,obj1相应的属性和方法不会改变
obj2.name = "李四";
console.log(obj1);
console.log(obj2);

  1. …运算符 var obj2 = {…obj1}
var obj1 = {
    name: "张三",
    age: 20,
    speak: function () {
        console.log("我是" + this.name);
    }
};

var obj2 = {
    ...obj1
};

// 当修改obj2的属性和方法的时候,obj1相应的属性和方法不会改变
obj2.name = "李四";
console.log(obj1);
console.log(obj2);

5.15.2.3 JSON.parse(JSON.stringify(obj))

实现对多维数组 多维对象的深拷贝
会忽略 undefined Symbol 函数

5.15.3 自己实现深拷贝

var obj1 = {
    name: "张三",
    age: 20,
    birthday: {
        year: 1997,
        month: 12,
        day: 5
    },
    speak: function () {
        console.log("我是" + this.name);
    }
};

var obj2 = deepClone(obj1);

// 当修改obj2的属性和方法的时候,obj1相应的属性和方法不会改变
obj2.name = "李四";
console.log(obj1);
console.log(obj2);

/**
 * 深拷贝通用方法
 * @param obj   需要拷贝的对象
 * @param has
 * @returns {any|RegExp|Date}
 */
function deepClone(obj, has = new WeakMap()) {
    // 类型检查
    if (obj == null) return obj;
    if (obj instanceof Date) return obj;
    if (obj instanceof RegExp) return obj;
    if (!(typeof obj == "object")) return obj;

    // 构造对象
    const newObj = new obj.constructor;

    // 防止自引用导致的死循环
    if (has.get(obj)) return has.get(obj);
    has.set(obj, newObj);

    // 循环遍历属性及方法
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            newObj[key] = deepClone(obj[key]);
        }
    }

    // 返回对象
    return newObj;
}


总结

本文从DOM BOM到JS高级 JSON AJAX Cookie 闭包 ES6新特性 对js做了一次复习,方便后续学习和参考,本文参考轻松的小希

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值