1、css3有哪些新增属性???
css 新特性
我知道的 C3 的新特性有很多,常见的如下:
- border-radius:圆角边框
- box-shadow:盒子阴影
- background-size:背景图片大小
- transition:过渡
- transform:转换(位移 旋转 缩放)
- animation:动画
- linear-gradient:线性渐变
- box-sizing:css3 盒子模型 2、git的核心概念有哪些???
git的三个核心概念(版本库,工作区,暂存区)
本文适合有一定的git基础的人阅读
Git和其他版本控制系统如SVN的一个不同之处就是有暂存区的概念,下面我以在windows系统中进行相关的讲解。
一、工作区(Working Directory)——其实就是一个文件夹
就是你在电脑里能看到的目录,比如我在F盘下面建了一个GitRepository文件夹,使用命令为:mkdir f:\GitRepository .那么这个GitRepository文件夹其实就是一个工作区。
二、版本库(Repository)——其实就是.git隐藏文件夹 在我们创建一个GitRpository文件夹之后,进入到该文件夹之后,使用命令 git init命令,则会创建版本库,即产生一个 .git隐藏文件夹 工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,暂存区有时候也称之为索引区。还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
那我们怎么去查看这个.git隐藏文件夹?因为我的事win10系统,可以在文件夹中通过“查看”勾选“隐藏的项目”既可以查看到隐藏文件夹了。
前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:比如我们添加一个tt.txt文本文件在GitRepository目录之下。这个文本文件只有一两个数字111.
f:\GitRepository>git add tt.txt f:\GitRepository>git commit -m "create successfully" [master (root-commit) 98e1592] create successfully 1 file changed, 1 insertion(+) create mode 100644 tt.txt 第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。
因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。
你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。
然后执行命令 git commit -a -m "insert successfully"
接下来,我们自己在GitRrpository这个目录下创建一个 ss.txt文本文件,并且添加一行文本 aaa,但是我们不去将这个 ss.txt文本文件add进去,这时候我们通过状态查看GitRepository下面两个文本文件的的状态:
f:\GitRepository>git status On branch master Untracked files: (use "git add ..." to include in what will be committed) //说明ss.txt没有添加进master里面去 ss.txt nothing added to commit but untracked files present (use "git add" to track)
总结: git add命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行 git commit就可以一次性把暂存区的所有修改提交到分支(branch)。
三、版本库的深入理解 下面一幅图片,从更深入的角度讲解了在底层到底是怎么工作的:
图中左侧为工作区,右侧为版本库。在版本库中标记为 "index" 的区域是暂存区(stage, index),标记为 "master" 的是 master 分支所代表的目录树。 图中我们可以看出此时 "HEAD" 实际是指向 master 分支的一个"游标"。所以图示的命令中出现 HEAD 的地方可以用 master 来替换。
图中的 objects 标识的区域为 Git 的对象库,实际位于 ".git/objects" 目录下,里面包含了创建的各种对象及内容。
当对工作区修改(或新增)的文件执行 "git add" 命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的ID被记录在暂存区的文件索引中。
当执行提交操作(git commit)时,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新。即 master 指向的目录树就是提交时暂存区的目录树。
当执行 "git reset HEAD" 命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。
当执行 "git rm --cached " 命令时,会直接从暂存区删除文件,工作区则不做出改变。
当执行 "git checkout ." 或者 "git checkout -- " 命令时,会用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区的改动。
当执行 "git checkout HEAD ." 或者 "git checkout HEAD " 命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。
———————————————— 版权声明:本文为CSDN博主「LoveMIss-Y」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:blog.csdn.net/qq_27825451…
3、git中的分支相关概念有哪些??? # 说说 Git 常用的命令有哪些?
#简版
- git add 提交文件到缓存区
- git commit 提交代码到本地仓库
- git pull 拉取远程仓库的分支与本地当前分支合并
- git fetch 拉取远程仓库的分支
- git push 上传本地指定分支到远程仓库
- git status 查看当前分支状态
- git diff 显示工作区中未添加至暂存区的内容与上一次 commit 的差异
- git checkout 新建一个分支或切换分支或撤销工作区文件更改
- git merge 合并指定分支到当前分支
(@徐济豪)
#一、前言
git的操作可以通过命令的形式如执行,日常使用就如下图 6 个命令即可
实际上,如果想要熟练使用,超过 60 多个命令需要了解,下面则介绍下常见的的git命令
#二、有哪些
#配置
Git自带一个 git config 的工具来帮助设置控制 Git外观和行为的配置变量,在我们安装完git之后,第一件事就是设置你的用户名和邮件地址
后续每一个提交都会使用这些信息,它们会写入到你的每一次提交中,不可更改
设置提交代码时的用户信息命令如下:
- git config [--global] user.name "[name]"
- git config [--global] user.email "[email address]"
#启动
一个git项目的初始有两个途径,分别是:
- git init [project-name]:创建或在当前目录初始化一个 git 代码库
- git clone url:下载一个项目和它的整个代码历史
#日常基本操作
在日常工作中,代码常用的基本操作如下:
- git init 初始化仓库,默认为 master 分支
- git add . 提交全部文件修改到缓存区
- git add <具体某个文件路径+全名> 提交某些文件到缓存区
- git diff 查看当前代码 add 后,会 add 哪些内容
- git diff --staged 查看现在 commit 提交后,会提交哪些内容
- git status 查看当前分支状态
- git pull <远程仓库名> <远程分支名> 拉取远程仓库的分支与本地当前分支合并
- git pull <远程仓库名> <远程分支名>:<本地分支名> 拉取远程仓库的分支与本地某个分支合并
- git commit -m "<注释>" 提交代码到本地仓库,并写提交注释
- git commit -v 提交时显示所有 diff 信息
- git commit --amend [file1] [file2] 重做上一次 commit,并包括指定文件的新变化
关于提交信息的格式,可以遵循以下的规则:
- feat: 新特性,添加功能
- fix: 修改 bug
- refactor: 代码重构
- docs: 文档修改
- style: 代码格式修改, 注意不是 css 修改
- test: 测试用例修改
- chore: 其他修改, 比如构建流程, 依赖管理
#分支操作
- git branch 查看本地所有分支
- git branch -r 查看远程所有分支
- git branch -a 查看本地和远程所有分支
- git merge <分支名> 合并分支
- git merge --abort 合并分支出现冲突时,取消合并,一切回到合并前的状态
- git branch <新分支名> 基于当前分支,新建一个分支
- git checkout --orphan <新分支名> 新建一个空分支(会保留之前分支的所有文件)
- git branch -D <分支名> 删除本地某个分支
- git push <远程库名> :<分支名> 删除远程某个分支
- git branch <新分支名称> <提交 ID> 从提交历史恢复某个删掉的某个分支
- git branch -m <原分支名> <新分支名> 分支更名
- git checkout <分支名> 切换到本地某个分支
- git checkout <远程库名>/<分支名> 切换到线上某个分支
- git checkout -b <新分支名> 把基于当前分支新建分支,并切换为这个分支
#远程同步
远程操作常见的命令:
- git fetch [remote] 下载远程仓库的所有变动
- git remote -v 显示所有远程仓库
- git pull [remote] [branch] 拉取远程仓库的分支与本地当前分支合并
- git fetch 获取线上最新版信息记录,不合并
- git push [remote] [branch] 上传本地指定分支到远程仓库
- git push [remote] --force 强行推送当前分支到远程仓库,即使有冲突
- git push [remote] --all 推送所有分支到远程仓库
#撤销
- git checkout [file] 恢复暂存区的指定文件到工作区
- git checkout [commit] [file] 恢复某个 commit 的指定文件到暂存区和工作区
- git checkout . 恢复暂存区的所有文件到工作区
- git reset [commit] 重置当前分支的指针为指定 commit,同时重置暂存区,但工作区不变
- git reset --hard 重置暂存区与工作区,与上一次 commit 保持一致
- git reset [file] 重置暂存区的指定文件,与上一次 commit 保持一致,但工作区不变
- git revert [commit] 后者的所有变化都将被前者抵消,并且应用到当前分支
reset:真实硬性回滚,目标版本后面的提交记录全部丢失了
revert:同样回滚,这个回滚操作相当于一个提价,目标版本后面的提交记录也全部都有
#存储操作
你正在进行项目中某一部分的工作,里面的东西处于一个比较杂乱的状态,而你想转到其他分支上进行一些工作,但又不想提交这些杂乱的代码,这时候可以将代码进行存储
- git stash 暂时将未提交的变化移除
- git stash pop 取出储藏中最后存入的工作状态进行恢复,会删除储藏
- git stash list 查看所有储藏中的工作
- git stash apply <储藏的名称> 取出储藏中对应的工作状态进行恢复,不会删除储藏
- git stash clear 清空所有储藏中的工作
- git stash drop <储藏的名称> 删除对应的某个储藏
#三、总结
git常用命令速查表如下所示:
#参考文献
- www.ruanyifeng.com/blog/2015/1…
- segmentfault.com/a/119000001…
4、标准盒模型与怪异(IE)盒模型的区别???
说说你对盒子模型的理解?
#简版
- 盒子模型组成有 4 部分,分别为:内容 内边距 外边距(一般不计入盒子实际宽度) 边框
- 盒子模型有 2 种:标准盒子模型与怪异盒子模型
- 标准盒子模型=content(内容)+border(边框)+padding(内边距)
- 怪异盒子模型=content(内容)(已经包含了 padding 和 border)
- css3 种可以通过设置 box-sizing 属性来完成标准或许怪异盒子模型之间的切换,怪异盒子模型:box-sizing: border-box;标准盒子模型:box-sizing:content-box
(@李金波)
#一、是什么
当对一个文档进行布局(layout)的时候,浏览器的渲染引擎会根据标准之一的 CSS 基础框盒模型(CSS basic box model),将所有元素表示为一个个矩形的盒子(box)
一个盒子由四个部分组成:content、padding、border、margin
content,即实际内容,显示文本和图像
boreder,即边框,围绕元素内容的内边距的一条或多条线,由粗细、样式、颜色三部分组成
padding,即内边距,清除内容周围的区域,内边距是透明的,取值不能为负,受盒子的background属性影响
margin,即外边距,在元素外创建额外的空白,空白通常指不能放其他元素的区域
上述是一个从二维的角度观察盒子,下面再看看看三维图:
下面来段代码:
<style>
.box {
width: 200px;
height: 100px;
padding: 20px;
}
</style>
<div class="box">盒子模型</div>
当我们在浏览器查看元素时,却发现元素的大小变成了`240px`
这是因为,在`CSS`中,盒子模型可以分成:
- W3C 标准盒子模型
- IE 怪异盒子模型
默认情况下,盒子模型为`W3C` 标准盒子模型
## [#](http://fanyouf.gitee.io/interview/css/03.html#%E4%BA%8C%E3%80%81%E6%A0%87%E5%87%86%E7%9B%92%E5%AD%90%E6%A8%A1%E5%9E%8B)二、标准盒子模型
标准盒子模型,是浏览器默认的盒子模型
下面看看标准盒子模型的模型图:

从上图可以看到:
- 盒子总宽度 = width + padding + border + margin;
- 盒子总高度 = height + padding + border + margin
也就是,`width/height` 只是内容高度,不包含 `padding` 和 `border`值
所以上面问题中,设置`width`为 200px,但由于存在`padding`,但实际上盒子的宽度有 240px
## [#](http://fanyouf.gitee.io/interview/css/03.html#%E4%B8%89%E3%80%81ie-%E6%80%AA%E5%BC%82%E7%9B%92%E5%AD%90%E6%A8%A1%E5%9E%8B)三、IE 怪异盒子模型
同样看看 IE 怪异盒子模型的模型图:

从上图可以看到:
- 盒子总宽度 = width + margin;
- 盒子总高度 = height + margin;
也就是,`width/height` 包含了 `padding`和 `border`值
## [#](http://fanyouf.gitee.io/interview/css/03.html#box-sizing)Box-sizing
CSS 中的 box-sizing 属性定义了引擎应该如何计算一个元素的总宽度和总高度
语法:
box-sizing: content-box|border-box|inherit:
1
- content-box 默认值,元素的 width/height 不包含 padding,border,与标准盒子模型表现一致
- border-box 元素的 width/height 包含 padding,border,与怪异盒子模型表现一致
- inherit 指定 box-sizing 属性的值,应该从父元素继承
回到上面的例子里,设置盒子为 border-box 模型
.box {
width: 200px;
height: 100px;
padding: 20px;
box-sizing: border-box;
}
#参考文献
最新修改: 10/25/2022, 10:08:51 PM
5、event loop事件循环如何理解??? ## 为什么JavaScript是单线程?
JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?
所以,为了避免复杂性,从一诞生,JavaScript就是单线程,这已经成了这门语言的核心特征,将来也不会改变。
为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。
同步任务和异步任务:
单线程,就是指一次只能完成一件任务,如果在同个时间有多个任务的话,这些任务就需要进行排队,前一个任务执行完,才会执行下一个任务。但如果有一个任务的执行时间很长,比如文件的读取或者数据的请求等等,那么后面的任务就要一直等待,这就会影响用户的使用体验。
为了解决这种情况,Javascript语言将任务的执行模式分成两种:同步(Synchronous)和异步(Asynchronous)。
同步模式: 就是前一个任务执行完成后,再执行下一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的;
异步模式: 则完全不同,每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行队列上的后一个任务,而是执行回调函数;后一个任务则是不等前一个任务的回调函数的执行而执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。
事件循环(Event Loop):
同步任务和异步任务分别进入不同的执行"场所"; 同步任务进入主线程,异步任务进入Event Table并注册回调函数。
当指定的事情完成时,Event Table会将这个函数移入任务队列(task quene),等待主线程的任务执行完毕;
当栈中的代码执行完毕,执行栈(call stack)中的任务为空时,就会读取任务队列(task quene)中的任务,去执行对应的回调;
如此循环,就形成js的事件循环机制(Event Loop)。
执行过程:
- 所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
- 遇到异步任务, 进入Event Table并注册回调函数; 等到指定的事件完成(如ajax请求响应返回, setTimeout延迟到指定时间)时,Event Table会将这个回调函数移入Event Queue。
- 当栈中的代码执行完毕,执行栈(call stack)中的任务为空时,主线程会先检查micro-task(微任务)队列中是否有任务,如果有,就将micro-task(微任务)队列中的所有任务依次执行,直到micro-task(微任务)队列为空; 之后再检查macro-task(宏任务)队列中是否有任务,如果有,则取出第一个macro-task(宏任务)加入到执行栈中,之后再清空执行栈,检查micro-task(微任务),以此循环,直到全部的任务都执行完成。
任务队列(task queue) 或 事件队列(event queue):
SetTimeout和promise都是异步任务,那么它们两个先执行谁呢?
其实在js中也是有一个机制,就是会分为宏任务和微任务。宏任务和微任务分别存放在不同的event queue,这两个队列分别为macrotack queue和microtack queue.
任务队列分为: macro-task(宏任务)队列, micro-task(微任务)队列;
在最新标准中,它们被分别称为task与jobs。
macro-task(宏任务):
- script(整体代码)
- setTimeout
- setInterval
- setImmediate
- I/O (比如Ajax操作从网络读取数据)
- UI render
micro-task(微任务):
- process.nextTick
- Promise
- Async/Await(实际就是promise)
- MutationObserver(html5新特性)
事件表格(Event Table):
Event Table 可以理解成一张事件->回调函数 对应表。
用来存储 JS 中的异步事件 (request, setTimeout, IO等) 及其对应的回调函数的列表。
当指定的事件完成(如ajax请求响应返回, setTimeout延迟到指定时间)时,Event Table会将这个回调函数移入Event Queue, 即macro-task(宏任务)队列 或 micro-task(微任务)队列。
6、js数组方法有哪些??? js数组方法大全
小爱同学-Allen
已于 2022-01-23 19:05:38 修改
1265 收藏 14 文章标签: javascript 前端 js数组方法 版权 在日常开发中,我们会接触到js中数组的一些方法,这些方法对我们来说,可以很遍历的达到我们想要的结果,但是因为方法比较多,有些方法也不常用,可能会过一段时间就会忘记,那么在这里我整理了31个数组的方法,供大家查阅。
1:concat(); 功能:合并数组,可以合并一个或多个数组,会返回合并数组之后的数据,不会改变原来的数组;
var str1 = [12,2,"hello"];var str2 = ["world"]; console.log(str1.concat(str2)); //[12, 2, "hello", "world"] console.log(str1); //[12,2,"hello"]; 也可以使用es6的扩展运算符,不会改变原数组
let str3 = [...str1,...str2] ** 2:join();** 功能:将数组转为字符串并返回转化的字符串数据,不会改变原来的数组; 注意:()中用双引号包括自己想用的分隔符,默认为逗号,这里方便观察,我用了-
var str1 = [12,2,"hello"]; var str2 = ["world"]; console.log(str1.join("-")); //12-2-hello console.log(str1); //[12, 2, "hello"] 3:pop(); 功能:删除数组的最后一位,并且返回删除的数据,会改变原来的数组
var str1 = [12,2,"hello"]; console.log(str1.pop() //hello console.log(str1); //[12, 2] 4:shift(); 功能:删除数组的第一位数据,并且返回新数组的长度,会改变原来的数组
var str1 = [12,2,"hello"]; console.log(str1.shift()); //12 console.log(str1); //[2,"hello"] 5:unshift(); 功能:在数组的首位新增一个或多数据,并且返回新数组的长度,会改变原来的数组 注意:unshift()方法返回的数据是新数组的长度,它增加的数据可以是一个也可以是多个,可以理解为增加一连串的数据,
var str1 = [12,2,"hello"]; var str2 = [43,2,"test"]; console.log(str1.unshift("你好")); //4 console.log(str2.unshift("hello","world")); //5 console.log(str1); //["你好", 12, 2, "hello"] console.log(str2); 6:push(); 功能:在数组的最后一位新增一个或多个数据,并且返回新数组的长度,会改变原来的数组 注意:push()方法返回的是数据是新数组的长度,它增加的数据可以是一个也可以是多个,可以理解为增加一连串的数据
var str1 = [12,2,"hello"]; var str2 = [43,2,"test"]; console.log(str1.push("你好")); //4 console.log(str2.push("hello","world")); //5 console.log(str1); //[12, 2, "hello","你好"] console.log(str2); //[43, 2, "test","hello", "world"] 7:reverse(); 功能:将数组的数据进行反转,并且返回反转后的数组,会改变原数组
var str1 = [12,2,"hello"]; console.log(str1.reverse()); //["hello", 2, 12] console.log(str1); //["hello", 2, 12] 8:sort(); 功能:对数组内的数据进行排序(默认为升序),并且返回排过序的新数组,会改变原来的数组 注意: 8.1:这里的排序是针对字符的排序,先使用数组的toString()方法转为字符串,再逐位比较,3是大于12的,因为首位3>1,不要与Number型的数据排序混淆 8.2:str2数组中增加了三个字符,可以看到,比较的时候,zoom是最大的,因为首位的英文字母通过ASCII码可以转为相应的数值,再根据数值比较
var str1 = [12,2,43,5,2,5]; var str2 = [92,2,43,"hello",5,2,5,"abc","zoom"]; console.log(str1.sort()); //[12, 2, 2, 43, 5, 5] console.log(str1); //[12, 2, 2, 43, 5, 5] console.log(str2.sort()); //[2, 2, 43, 5, 5, 92, "abc", "hello", "zoom"] console.log(str2); //[2, 2, 43, 5, 5, 92, "abc", "hello", "zoom"] 8.3:排序问题 参数:sort(callback) 如果需要按照数值排序,需要传参。sort(callback),callback为回调函数,该函数应该具有两个参数,比较这两个参数,然后返回一个用于说明这两个值的相对顺序的数字(a-b)。其返回值如下: 若 a 小于 b,返回一个小于 0 的值。 若 a 等于 b,则返回 0。 若 a 大于 b,则返回一个大于 0 的值。
var str3 = [92,2,43,5,2,5];
console.log(str3.sort(fn)); //[2, 2, 5, 5, 43, 92]
console.log(str3); //[2, 2, 5, 5, 43, 92]
function fn (a,b){
return a-b;
}
9:slice();
功能:截取指定位置的数组,并且返回截取的数组,不会改变原数组
参数:slice(startIndex, endIndex)
注意:可从已有的数组中返回选定的元素。该方法接收两个参数slice(start,end),strat为必选,表示从第几位开始;end为可选,表示到第几位结束(不包含end位),省略表示到最后一位;start和end都可以为负数,负数时表示从最后一位开始算起,如-1表示最后一位。
var arr = ["T1","J1","L1","L2","M1"]; console.log(arr.slice(1,3)); //["J1","L1"] console.log(arr.slice(1)); //["J1","L1","L2","M1"] console.log(arr.slice(-4,-1)); //["J1","L1","L2"] console.log(arr.slice(-2)); //["Lily","M1"] console.log(arr.slice(1,-2)); //["J1","L1"] console.log(arr); //["T1","J1","L1","L2","M1"] 10:splice() 功能:向数组中添加,或从数组删除,或替换数组中的元素,然后返回被删除/替换的元素。 参数:splice(start,num,data1,data2,…); 所有参数全部可选。第一个参数是小标,第二个是删除的长度,第一个参数可以为负数
var list = [1, 2, 3] console.log(list); // [1, 2, 3]
// 删除 list.splice(0,1); // 删除 -> 从下标为0开始,长度为1 console.log(list); // [2,3] list.splice(0,2); // 删除 -> 从下标为0开始,长度为2 console.log(list); // []
//替换 list.splice(0,1,4); // 替换 -> 从下标为0开始,长度为1的数组元素替换成4 console.log(list); // [4,2,3] list.splice(0,2,4); // 替换 -> 从下标为0开始,长度为2的数组元素替换成4(即4,2整体替换成4) console.log(list); // [4,3]
//添加 list.splice(1,0,5); // 表示在下标为1处添加一项5 console.log(list); // [1,5,2,3]
如果第一个参数为负数就从后面往前数,入上图 splice会改变原数组
11:toString(); 功能:将数组转换成字符串,类似于没有参数的join()。该方法会在数据发生隐式类型转换时被自动调用,如果手动调用,就是直接转为字符串。不会改变原数组
var str = [1,2,3]; console.log(str.toString()); //1,2,3 console.log(str); //[1,2,3] 12:valueOf(); 功能:返回数组的原始值(一般情况下其实就是数组自身),一般由js在后台调用,并不显式的出现在代码中
var str = [1,2,3]; console.log(str.valueOf()); //[1,2,3] console.log(str); //[1,2,3] //为了证明返回的是数组自身 console.log(str.valueOf() == str); //true 13:IndexOf(); 功能:根据指定的数据,从左向右,查询在数组中出现的位置,如果不存在指定的数据,返回-1,找到了指定的数据返回该数据的索引 参数:indexOf(value, start);value为要查询的数据;start为可选,表示开始查询的位置,当start为负数时,从数组的尾部向前数;如果查询不到value的存在,则方法返回-1 注意:如果找到该数据,立即返回该数据的索引,不再往后继续查找
var str = ["h","e","l","l","o"]; console.log(str.indexOf("l")); //2 console.log(str.indexOf("l",3)); //3 console.log(str.indexOf("l",4)); //-1 console.log(str.indexOf("l",-1)); //-1 console.log(str.indexOf("l",-3)); //2 14:lastIndexOf(); 功能:根据指定的数据,从左向右,lastIndexOf() 方法可返回一个指定的元素在数组中最后出现的位置,从该字符串的后面向前查找。如果不存在指定的数据,返回-1,找到了指定的数据返回该数据的索引 参数:indexOf(value, start);value为要查询的数据;start为可选,表示开始查询的位置,当start为负数时,从数组的尾部向前数;如果查询不到value的存在,则方法返回-1
var str = ["h","e","l","l","o"]; console.log(str.lastIndexOf("l")); // 根据我的发现,indexOf的第二个参数传进去有用,lastIndexOf第二个参数跟没传一样
15:forEach(); 功能:ES5新增的方法,用来遍历数组,没有返回值, 参数:forEach(callback);callback默认有三个参数,分别为value(遍历到的数组的数据),index(对应的索引),self(数组自身)。
var arr = ["Tom","Jack","Lucy","Lily","May"]; var a = arr.forEach(function(value,index,self){ console.log(value + "--" + index + "--" + (arr === self)); }) // 打印结果为: // Tom--0--true // Jack--1--true // Lucy--2--true // Lily--3--true // May--4--true console.log(a); //undefined---forEach没有返回值 //该方法为遍历方法,不会修改原数组 16:map(); 功能: 1.同forEach功能; 2.map的回调函数会将执行结果返回,最后map将所有回调函数的返回值组成新数组返回。 参数:map(callback);callback默认有三个参数,分别为value,index,self。跟上面的forEach()的参数一样
//功能1:同forEach var arr = ["Tom","Jack","Lucy","Lily","May"]; var a = arr.map(function(value,index,self){ console.log(value + "--" + index + "--" + (arr === self)) }) // 打印结果为: // Tom--0--true // Jack--1--true // Lucy--2--true // Lily--3--true // May--4--true
//功能2:每次回调函数的返回值被map组成新数组返回 var arr = ["Tom","Jack","Lucy","Lily","May"]; var a = arr.map(function(value,index,self){ return "hi:"+value; }) console.log(a); //["hi:Tom", "hi:Jack", "hi:Lucy", "hi:Lily", "hi:May"] console.log(arr); //["Tom", "Jack", "Lucy", "Lily", "May"]---原数组未改变
17:filter(); 功能:1.同forEach功能;2.filter的回调函数需要返回布尔值,当为true时,将本次数组的数据返回给filter,最后filter将所有回调函数的返回值组成新数组返回(此功能可理解为“过滤”)。 参数:filter(callback);callback默认有三个参数,分别为value,index,self。
//功能1:同forEach var arr = ["Tom","Jack","Lucy","Lily","May"]; var a = arr.filter(function(value,index,self){ console.log(value + "--" + index + "--" + (arr === self)) }) // 打印结果为: // Tom--0--true // Jack--1--true // Lucy--2--true // Lily--3--true // May--4--true
//功能2:当回调函数的返回值为true时,本次的数组值返回给filter,被filter组成新数组返回 var arr = ["Tom","Jack","Lucy","Lily","May"]; var a = arr.filter(function(value,index,self){ return value.length > 3; }) console.log(a); //["Jack", "Lucy", "Lily"] console.log(arr); //["Tom", "Jack", "Lucy", "Lily", "May"]---原数组未改变
18:every(); 功能:判断数组中每一项是否都满足条件,只有所有项都满足条件,才会返回true。 参数:every()接收一个回调函数作为参数,这个回调函数需要有返回值,every(callback);callback默认有三个参数,分别为value,index,self。 功能1:当回调函数的返回值为true时,类似于forEach的功能,遍历所有;如果为false,那么停止执行,后面的数据不再遍历,停在第一个返回false的位置。
//demo1: var arr = ["Tom","abc","Jack","Lucy","Lily","May"]; var a = arr.every(function(value,index,self){ console.log(value + "--" + index + "--" + (arr == self)) }) // 打印结果为: // Tom--0--true //因为回调函数中没有return true,默认返回undefined,等同于返回false
//demo2: var arr = ["Tom","abc","Jack","Lucy","Lily","May"]; var a = arr.every(function(value,index,self){ console.log(value + "--" + index + "--" + (arr == self)) return value.length < 4; }) // 打印结果为: // Tom--0--true // abc--1--true // Jack--2--true //因为当遍历到Jack时,回调函数到return返回false,此时Jack已经遍历,但是后面数据就不再被遍历了
//demo3: var arr = ["Tom","abc","Jack","Lucy","Lily","May"]; var a = arr.every(function(value,index,self){ console.log(value + "--" + index + "--" + (arr == self)) return true; }) // 打印结果为: // Tom--0--true // abc--1--true // Jack--2--true // Lucy--3--true // Lily--4--true // May--5--true //因为每个回调函数的返回值都是true,那么会遍历数组所有数据,等同于forEach功能
功能2:当每个回调函数的返回值都为true时,every的返回值为true,只要有一个回调函数的返回值为false,every的返回值都为false
//demo1: var arr = ["Tom","abc","Jack","Lucy","Lily","May"]; var a = arr.every(function(value,index,self){ return value.length > 3; }) console.log(a); //false
//demo2: var arr = ["Tom","abc","Jack","Lucy","Lily","May"]; var a = arr.every(function(value,index,self){ return value.length > 2; }) console.log(a); //true
19:some(); 功能:判断数组中是否存在满足条件的项,只要有一项满足条件,就会返回true。 参数:some()接收一个回调函数作为参数,这个回调函数需要有返回值,some(callback);callback默认有三个参数,分别为value,index,self。 功能1:因为要判断数组中的每一项,只要有一个回调函数返回true,some都会返回true,所以与every正好相反,当遇到一个回调函数的返回值为true时,可以确定结果,那么停止执行,后面都数据不再遍历,停在第一个返回true的位置;当回调函数的返回值为false时,需要继续向后执行,到最后才能确定结果,所以会遍历所有数据,实现类似于forEach的功能,遍历所有。
//demo1: var arr = ["Tom","abc","Jack","Lucy","Lily","May"]; var a = arr.some(function(value,index,self){ console.log(value + "--" + index + "--" + (arr == self)) return value.length > 3; }) // 打印结果为: // Tom--0--true // abc--1--true // Jack--2--true
20.reduce(); 迭代数组的所有项,累加器,数组中的每个值(从左到右)合并,最终计算为一个值 参数: callback: previousValue 必选 --上一次调用回调返回的值,或者是提供的初始值(initialValue) currentValue 必选 --数组中当前被处理的数组项 index 可选 --当前数组项在数组中的索引值 array 可选 --原数组 initialValue: 可选 --初始值 实行方法:回调函数第一次执行时,preValue 和 curValue 可以是一个值,如果 initialValue 在调用 reduce() 时被提供,那么第一个 preValue 等于 initialValue ,并且curValue 等于数组中的第一个值;如果initialValue 未被提供,那么preValue 等于数组中的第一个值.
let arr = [0,1,2,3,4] let arr1 = arr.reduce((preValue, curValue) => preValue + curValue ) console.log(arr1) // 10 let arr2 = arr.reduce((preValue,curValue)=>preValue + curValue,5) console.log(arr2) // 15
arr.reduce()拓展(高级用法) (1)计算数组中每个元素出现的次数
let names = ['peter', 'tom', 'mary', 'bob', 'tom','peter']; let nameNum = names.reduce((pre,cur)=>{ if(cur in pre){ pre[cur]++ }else{ pre[cur] = 1 } return pre },{}) console.log(nameNum); //{ peter: 2, tom: 2, mary: 1, bob: 1 }
(2)数组去重
let arr = [1,2,3,4,4,1] let newArr = arr.reduce((pre,cur)=>{ if(!pre.includes(cur)){ return pre.concat(cur) }else{ return pre } },[]) console.log(newArr);// [1, 2, 3, 4]
(3)将多维数组转化为一维
let arr = [[0, 1], [2, 3], [4,[5,6,7]]] const newArr = function(arr){ return arr.reduce((pre,cur)=>pre.concat(Array.isArray(cur)?newArr(cur):cur),[]) } console.log(newArr(arr)); //[0, 1, 2, 3, 4, 5, 6, 7]
21.reduceRight() 功能:(与reduce类似)从数组的最后一项开始,向前逐个遍历到第一位,迭代数组的所有项,然后构建一个最终返回的值。 参数:同reduce。 demo:同reduce
22 Array.from() 将伪数组变成数组,就是只要有length的就可以转成数组。 —es6
let str = '12345' console.log(Array.from(str)) // ["1", "2", "3", "4", "5"] let obj = {0:'a',1:'b',length:2} console.log(Array.from(obj)) // ["a", "b"] let aa= {0:'a',1:'b'} console.log(Array.from(aa)) // []
原来的不会发生改变
23 Array.of() 将一组值转换成数组,类似于声明数组 —es6
let str = '11' console.log(Array.of(str)) // ['11'] // 等价于 console.log(new Array('11')) // ['11]
ps:但是new Array()有缺点,就是参数问题引起的重载
console.log(new Array(2)) //[empty × 2] 是个空数组 console.log(Array.of(2)) // [2]
24 arr.copyWithin() 在当前数组内部,将制定位置的数组复制到其他位置,会覆盖原数组项,返回当前数组 参数: target --必选 索引从该位置开始替换数组项 start --可选 索引从该位置开始读取数组项,默认为0.如果为负值,则从右往左读。 end --可选 索引到该位置停止读取的数组项,默认是Array.length,如果是负值,表示倒数
let arr = [1,2,3,4,5,6,7] let arr1 = arr.copyWithin(1) console.log(arr1) // [1, 1, 2, 3, 4, 5, 6] let arr2 = arr.copyWithin(1,2) console.log(arr2) // [1, 2, 3, 4, 5, 6, 6] let arr3 = arr.copyWithin(1,2,4) console.log(arr3) // [1, 3, 4, 4, 5, 6, 6]
25 arr.find(callback) 找到第一个符合条件的数组成员
let arr = [1,2,3,4,5,2,4] let arr1 = arr.find((value, index, array) =>value > 2) console.log(arr1) // 3
26 arr.findIndex(callback) 找到第一个符合条件的数组成员的索引值
let arr = [1,2,3,4,5] let arr1 = arr.findIndex((value, index, array) => value > 3) console.log(arr1) // 3
27 arr.fill(target, start, end) 使用给定的值,填充一个数组,ps:填充完后会改变原数组 参数: target – 待填充的元素 start – 开始填充的位置-索引 end – 终止填充的位置-索引(不包括该位置)
let arr = [1,2,3,4,5] let arr1 = arr.fill(5) console.log(arr1) // [5, 5, 5, 5, 5] console.log(arr) // [5, 5, 5, 5, 5] let arr2 = arr.fill(5,2) console.log(arr2) let arr3 = arr.fill(5,1,3) console.log(arr3)
28 arr.includes() 判断数中是否包含给定的值
let arr = [1,2,3,4,5]
let arr1 = arr.includes(2)
console.log(arr1) // ture
let arr2 = arr.includes(9)
console.log(arr2) // false
let arr3 = [1,2,3,NaN].includes(NaN)
console.log(arr3) // true
ps:与indexOf()的区别: indexOf()返回的是数值,而includes()返回的是布尔值 indexOf() 不能判断NaN,返回为-1 ,includes()则可以判断、
29 arr.keys() 遍历数组的键名
let arr = [1,2,3,4] let arr2 = arr.keys() for (let key of arr2) { console.log(key); // 0,1,2,3 }
30 arr.values() 遍历数组键值
let arr = [1,2,3,4] let arr1 = arr.values() for (let val of arr1) { console.log(val); // 1,2,3,4 }
31 arr.entries() 遍历数组的键名和键值
let arr = [1,2,3,4] let arr1 = arr.entries() for (let e of arr1) { console.log(e); // [0,1] [1,2] [2,3] [3,4] }
entries() 方法返回迭代数组。 迭代数组中每个值 前一个是索引值作为 key, 数组后一个值作为 value。
哪些数组方法会改变原数组 unshift(); push(); shift(); pop(); sort(); reverse(); splice(); copyWithin() fill() 这九个数组方法在上面都有过介绍了,可以看出,再用这些方法的时候,原数组是会被改变的。 ———————————————— 版权声明:本文为CSDN博主「小爱同学-Allen」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:blog.csdn.net/qq_34595425…
7、拓展运算符与rest剩余参数是什么意思,应用场景??? 1、扩展运算符简介 扩展运算符( spread )是三个点(…),可以将一个数组转为用逗号分隔的参数序列。
总的来说就是把一个大元素给打散成一个个单独的小元素。
基本用法:拆解字符串与数组
var array = [1,2,3,4]; console.log(...array);//1 2 3 4 var str = "String"; console.log(...str);//S t r i n g
2、扩展运算符应用 2.1 某些场景可以替代apply
在使用Math.max()求数组的最大值时,ES5可以通过 apply 做到(用一种不友好且繁琐的方式)
// ES5 apply 写法 var array = [1,2,3,4,3]; var max1 = Math.max.apply(null,array); console.log(max1);//4
幸运的是JavaScript的世界在不断改变,扩展运算符可用于数组的析构,优雅的解决了这个问题。
// ES6 扩展运算符 写法
var array = [1,2,3,4,3];
var max2 = Math.max(...array);
console.log(max2);//4
先把 array 打散成 1 2 3 4 3,再在里面找最大的那一个,就显而易见了。
2.2 代替数组的push、concat 等方法
实现把 arr2 塞到 arr1 中
// ES5 apply 写法 var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; Array.prototype.push.apply(arr1, arr2); //arr1 [0, 1, 2, 3, 4, 5]
扩展运算符又要施展化骨大法了
// ES6 扩展运算符 写法 var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; arr1.push(...arr2); //arr1 [0, 1, 2, 3, 4, 5]
通俗的解释下, 扩展运算符先把 arr2 打散成 3 4 5 , 之后再往arr1里push,就轻松多了。
同理可推,concat 合并数组的时候:
var arr1 = ['a', 'b']; var arr2 = ['c']; var arr3 = ['d', 'e'];
// ES5的合并数组 arr1.concat(arr2, arr3) // [ 'a', 'b', 'c', 'd', 'e' ]
// ES6的合并数组 [...arr1, ...arr2, ...arr3] // [ 'a', 'b', 'c', 'd', 'e' ]
ES5的合并数组写法,像是 arr1 把 arr2,arr3 给吸收了。
而ES6的合并数组写法,则是先把 arr1,arr2, arr3 拆解,之后塞到新的数组中。
2.3 拷贝数组或对象
//拷贝数组 var array0 = [1,2,3]; var array1 = [...array0]; console.log(array1);//[1, 2, 3]
//拷贝数组 var obj = { age:1, name:"lis", arr:{ a1:[1,2] } } var obj2 = {...obj}; console.log(obj2);//{age: 1, name: "lis", arr: {…}}
无论是像克隆数组还是对象,先用化骨绵掌之扩展运算符,将其打散,之后再拼装的到一起就可以了,多么简单易用。
2.4 将伪数组转化为数组
//伪数组转换为数组 var nodeList = document.querySelectorAll('div'); console.log([...nodeList]); // [div, div, div ... ]
上面代码中,querySelectorAll 方法返回的是一个 nodeList 对象。它不是数组,而是一个类似数组的对象。
这时,扩展运算符可以将其转为真正的数组,原因就在于 NodeList 对象实现了 Iterator。
注意:使用扩展运算符将伪数组转换为数组有局限性,这个类数组必须得有默认的迭代器且伪可遍历的。
3、rest 运算符简介 剩余运算符(the rest operator),它的样子看起来和展开操作符一样,但是它是用于解构数组和对象。在某种程
度上,剩余元素和展开元素相反,展开元素会“展开”数组变成多个元素,剩余元素会收集多个元素和“压缩”成一个
单一的元素。
说的通俗点,有点像吸星大法,收集多个元素,压缩成单一的元素 。
rest参数用于获取函数的多余参数,这样就不需要使用arguments对象了。rest参数搭配的变量是一个数组,该变
量将多余的参数放入数组中。
例如实现计算传入所有参数的和
使用arguments参数:
function sumArgu () { var result = 0; for (var i = 0; i < arguments.length; i++) { result += arguments[i]; } return result } console.log(sumArgu(1,2,3));//6
使用rest参数:
function sumRest (...m) { var total = 0; for(var i of m){ total += i; } return total; } console.log(sumRest(1,2,3));//6
上面代码利用 rest 参数,可以向该函数传入任意数目的参数。传递给 sumRest 函数的一组参数值,被整合成了数组 m。
就像是吸星大法,把分散的元素收集到一起。
所以在某些场景中,无需将arguments转为真正的数组,可以直接使用rest参数代替。
4、rest 运算符应用 4.1 rest 参数代替arguments变量
// arguments变量的写法 function sortNumbers() { return Array.prototype.slice.call(arguments).sort(); }
// rest参数的写法 const sortNumbers = (...numbers) => numbers.sort();
上面的两种写法,比较后可以发现,rest 参数的写法更自然也更简洁。
4.2 与解构赋值组合使用
var array = [1,2,3,4,5,6]; var [a,b,...c] = array; console.log(a);//1 console.log(b);//2 console.log(c);//[3, 4, 5, 6]
备注:rest参数可理解为剩余的参数,所以必须在最后一位定义,如果定义在中间会报错。
var array = [1,2,3,4,5,6]; var [a,b,...c,d,e] = array; // Uncaught SyntaxError: Rest element must be last element
5、总结 5.1 扩展运算符和rest运算符是逆运算
扩展运算符:数组=>分割序列
rest运算符:分割序列=>数组
5.2 扩展运算符应用场景
由于其繁琐的语法,apply 方法使用起来并不是很方便。当需要拿一个数组的元素作为函数调用的参数时,
扩展运算符是一个不错的选择。
扩展运算符还改善了数组字面量的操作,你可以更方便的初始化、连接、复制数组了。
使用析构赋值你可以提取数组的一部分。通过与迭代器协议的组合,你可以以一种更灵活的方式使用该表达式。
5.3 rest运算符应用场景
rest运算符主要是处理不定数量参数,rest参数使得收集参数变得非常简单。它是类数组对象arguments一个合理的替代品。
rest参数还可以与解构赋值组合使用。
在实际项目中灵活应用扩展运算符、rest运算符,能写出更精简、易读性高的代码。 ———————————————— 版权声明:本文为CSDN博主「Vicentekw」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:blog.csdn.net/hkw20/artic…
8、ES6新增数据结构set和map是什么???它们中的哪一个可以实现数组去重及相关代码。 一、什么是set Set 是唯一值的集合,类似于数组。 一个 Set 可以容纳任何数据类型的任何值。 每个值在 Set 中只能出现一次,因此常用做数组去重。 另外想要了解其他数组去重的方法可以去看看我之前写的一篇文章,《【超全整理】JS数组去重到底有几种方法?》
Set 对象的几个常用方法和属性 new Set() 创建新的 Set 对象。 add() 向 Set 添加新元素。 clear() 从 Set 中删除所有元素。 delete() 删除由其值指定的元素。 has() 如果值存在则返回 true。 forEach() 为每个元素调用回调。 keys() 返回 Set 对象中值的数组。 size 返回元素个数。
类型转换 // Array 转 Set var mySet = new Set(["value1", "value2", "value3"]); // 用...操作符,将 Set 转 Array var myArray = [...mySet]; String // String 转 Set var mySet = new Set('hello'); // Set(4) {"h", "e", "l", "o"} // 注:Set 中 toString 方法不能将 Set 转换成 String
Set 对象作用 1.去重
var mySet = new Set([1, 2, 3, 4, 4]); [...mySet]; // [1, 2, 3, 4]
2.求并集
var a = new Set([1, 2, 3]); var b = new Set([4, 3, 2]); var union = new Set([...a, ...b]); // {1, 2, 3, 4}
3.求交集
var a = new Set([1, 2, 3]); var b = new Set([4, 3, 2]); var intersect = new Set([...a].filter(x => b.has(x))); // {2, 3}
4.求差集
var a = new Set([1, 2, 3]); var b = new Set([4, 3, 2]); var difference = new Set([...a].filter(x => !b.has(x))); // {1}
二、什么是map Map 对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。 Map 对象记得键的原始插入顺序。 Map 对象具有表示映射大小的属性。
Map 对象的几个常用方法和属性 new Map() 创建新的 Map 对象。 set() 为 Map 对象中的键设置值。 get() 获取 Map 对象中键的值。 entries() 返回 Map 对象中键/值对的数组。 keys() 返回 Map 对象中键的数组。 values() 返回 Map 对象中值的数组。
Map对象的遍历 1.for…of var myMap = new Map(); myMap.set(0, "zero"); myMap.set(1, "one");
// 将会显示两个 log。 一个是 "0 = zero" 另一个是 "1 = one" for (var [key, value] of myMap) { console.log(key + " = " + value); } for (var [key, value] of myMap.entries()) { console.log(key + " = " + value); } /* 这个 entries 方法返回一个新的 Iterator 对象,它按插入顺序包含了 Map 对象中每个元素的 [key, value] 数组。 */
// 将会显示两个log。 一个是 "0" 另一个是 "1" for (var key of myMap.keys()) { console.log(key); } /* 这个 keys 方法返回一个新的 Iterator 对象, 它按插入顺序包含了 Map 对象中每个元素的键。 */
// 将会显示两个log。 一个是 "zero" 另一个是 "one" for (var value of myMap.values()) { console.log(value); } /* 这个 values 方法返回一个新的 Iterator 对象,它按插入顺序包含了 Map 对象中每个元素的值。 */
2.forEach() var myMap = new Map(); myMap.set(0, "zero"); myMap.set(1, "one");
// 将会显示两个 logs。 一个是 "0 = zero" 另一个是 "1 = one" myMap.forEach(function(value, key) { console.log(key + " = " + value); }, myMap)
Map 对象的操作 Map 与 Array的转换 var kvArray = [["key1", "value1"], ["key2", "value2"]];
// Map 构造函数可以将一个 二维 键值对数组转换成一个 Map 对象 var myMap = new Map(kvArray);
// 使用 Array.from 函数可以将一个 Map 对象转换成一个二维键值对数组 var outArray = Array.from(myMap);
Map 的克隆 var myMap1 = new Map([["key1", "value1"], ["key2", "value2"]]); var myMap2 = new Map(myMap1);
console.log(original === clone); // 打印 false。 Map 对象构造函数生成实例,迭代出新的对象。
Map 的合并 ar first = new Map([[1, 'one'], [2, 'two'], [3, 'three'],]); var second = new Map([[1, 'uno'], [2, 'dos']]);
// 合并两个 Map 对象时,如果有重复的键值,则后面的会覆盖前面的,对应值即 uno,dos, three var merged = new Map([...first, ...second]);
三、map和object的区别 二者都是以key-value的形式对数据进行存储;
1.key的数据类型范围不同 obj可以作为key的仅有number、string、symbol。 map均可以。
2.key的顺序不同。 obj通过obj.keys()打印出来的属性顺序是 number–字符串 map的key顺序是声明顺序。
3.创建方式不同。 obj有三种创建方式 字面量{}、new Object() 、构造函数。 map仅支持new Map()
4.key的调用不同。 map只能用原生的get方法调用。
5.设置属性的方式不同 map只能使用set(key,val)方法设置属性。
6.Size属性 map有size属性,对象没有。Map.size 返回 Map 中元素的数量,而 Object 的键值对个数只能手动计算 ———————————————— 版权声明:本文为CSDN博主「new个对象玩游戏」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:blog.csdn.net/weixin_4404…
9、说一下你理解的promise、以及promise封装一个网络请求,核心代码??? 一、Promise 介绍 定义
Promise 是异步编程的一种解决方法,比传统的回调函数和事件更合理;它是由社区提出和实现经由 ES6 将其写进语言标准,并在原生提供了 Promise 对象; Promise 可以理解是一个容器,里面保存着某个将来才会结束的事件(异步操作)的结果;从语法上说,Promise 是一个对象通过它可以获取异步操作的消息;Promise 提供了统一的 API ,各种异步操作都可以用同样的方法进行处理。 特点
Promise 对象代表一个异步操作,对象的状态不受外界影响,有三种状态,pending(进行中)、fulfilled(已成功)、rejected(已失败);只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态; 一旦状态改变就不会再变,Promise 对象的状态改变,只有两种可能:从 pending 变为 fulfilled,从 pending 变为 rejected;如果改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果;这与事件(event)完全不同,事件的特点是:如果你错过了它,再去监听是得不到结果的; 构造函数 Promise 必须接收一个函数(handle)作为参数,函数又包含 resolve 和 reject ; then 、catch 支持链式调用; 缺点
Promise 无法取消:一旦新建就会执行,无法中途取消; 如果不设置回调函数,Promise 内部抛出的错误不会反应到外部; 当处于 pendding 状态时,无法知道目前进展到哪一个阶段; 场景
有效的解决 js 异步回调地狱问题; 将业务逻辑与数据处理分隔开使代码更优雅,方便阅读,更有利于代码维护; 基本用法
let p = new Promise(function(resolve,reject){ setTimeout(function(){ resolve('成功!'); },10) }).then(res=>{ console.log('成功!') }) ———————————————— 版权声明:本文为CSDN博主「三个木马人」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:blog.csdn.net/weixin_4329…
使用promise封装ajax请求
尚硅谷铁粉
于 2022-02-11 14:36:18 发布
3525 收藏 19 分类专栏: java 文章标签: ajax javascript 前端 版权
java 专栏收录该内容 108 篇文章4 订阅 订阅专栏
首先作为前端开发人员,大家都应该使用过Ajax发送请求,目前市面上流行的发送Ajax请求的方式为以下三种:
Jquery的$.ajax() 尤雨溪推荐的axios es6新出的fetch方法 这三种方法的区别详见文章ajax三种方式的区别,这里不再详细解释。
本篇文章主要讲工作中是如何使用ajax请求,也就是让ajax结合promise使用。
1.为什么要包装ajax? 小明同学说:“直接发送ajax请求不就得了,干嘛那么麻烦。”于是小明很顺畅的写下以下代码:
//以.ajax({ type:"POST", url:"http://localhost:5000/login", data:{ username:"admin", password:"admin" }, dataType:"json", success:function (data) { console.log(data); }, error:function (err) { console.log(err); } }) 要知道,我们一个完整的项目势必会涉及到大量Ajax请求,如果我们每个请求都直接写Ajax请求,那么即使是请求同一个地址,只要发送的data参数产生了变化,就要重新写一遍ajax请求。很明显,这种写法会有以下几个缺点:
代码重复率很高,过于臃肿 代码可读性很差,不利于后期的维护 所以这种最"直接"的写法真所谓的费力不讨好,代码量变大,最后的效果反而不好,所以在工作中一定要避免重复劳动。前端培训
2.为什么要选择promise封装ajax? 看到上面的缺点,另外一位同学小刚说:“OK,我封装Ajax,但我直接用函数封装,不用Promise封装,那不是也可以避免重复劳动嘛。”于是小刚写下以下代码:
function ajax(url,data={},type="GET",callback){ $.ajax({ type:type, url:url, data:data, dataType:"json", success:function (data) { callback(data); } }) } let url="http://localhost:5000/login"; let data={ username:"admin", password:"admin" } function callback(data){ console.log(data) } ajax(url,data,"GET",callback); ajax(url,data,"POST",callback); 确实,直接用函数封装的写法可以克服重复书写Ajax的缺点,但是还是无法解决“回调地狱”的问题,也就是当如果有多个回调处理函数时,如:f1(f2(f3)),但是采用Promise封装ajax请求就可以完美解决这个问题,最后写出以下代码:
function ajax(url,data={},type="GET"){ return new Promise((resolve, reject) => { $.ajax({ type:type, url:url, data:data, dataType:"json", success:function (data) { resolve(data); }, error:function (err) { reject(err); } }) }) } let url="http://localhost:5000/login"; let data={ username:"admin", password:"admin" } let promise=ajax(url,data,"GET");//注意这里返回的是promise对象 promise.then(data=>{ //f1为第一个回调处理函数 f1(data); }).then(data2=>{ //f2为第二个回调处理函数 f2(data2); }).catch(err=>{ console.log(err); }) 一下这一行代码很重要,一定要记住:
return new Promise((resolve, reject) => {
})
———————————————— 版权声明:本文为CSDN博主「尚硅谷铁粉」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:blog.csdn.net/zjjcchina/a…
10、说一下es6的导入导出如何使用??
ES6 的三种导入导出 2.1 默认导出和导入 默认导出的语法: export default {默认导出的成员}
默认导入的语法: import 变量名称 from '模块路径'
导出文件.js
const a = 10 const b = 20 const fn = () => { console.log("模块内 - 箭头函数") }
// 导出 export default { // 导出对象,里面装集体的key和上面值 a, b:b, myFn:fn } 导入文件.js
// 注意: .js后缀名必须得写 -babel不会自动去添加后缀名 import Obj from "./导出文件.js" console.log(Obj) 补充:
如果在html文件使用 导入文件.js 的时候,需要注意:
1.使用模块的那个文件引入进来
2.浏览器对import支持性还不高,需要babel.js预处理(import翻译成浏览器认识的代码)后,再被浏览器执行
3.引入babel.js,给import代码的标签添加type='text/babel',告诉浏览器这个script代码要被babel处理后你再来执行
2.2 按需导出和导入 按需导出的语法: export const s1 = 10 export const 变量名 = 值(普通值/函数)
按需导入的语法: import {按需导入的名称} from '模块路径'
// 按需导出的方式 export const a = 10 export const b = 20 export const fn = () => { console.log("模块内 - 箭头函数") }
// 按需导入 // 补充: 可以用as关键字给变量起别名 import {fn as theFn,a} from './text6.js' console.log(theFn,a) 补充:
1.可以用as关键字给变量起别名
-
. 代表当前文件所在文件夹 ./ 访问当前文件夹下的东西 如果不写 ./ 默认找同级目录下的这个文件
3.按需导入导出可以和默认导入导出同时在一个文件夹里使用,但是按需导入导出可以使用多次,默认导入导出只能使用一次
2.3 无变量直接导入一个模块 无导出.js
for(let i = 0, i < 10; i++) { console.log(i) }
// 无导出,就是一个普通要执行的模块 导入.js
import "./无导出.js"
// 目的:为了让模块文件执行一次 ———————————————— 版权声明:本文为CSDN博主「蓝爱人」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:blog.csdn.net/weixin_4641…