赞
踩
大数据类型使用 bigInt
null 有数据位置但是没有数据,undefined 是完全没有数据位置
object{} 对象,array[]数组
if 中如果没有写判断语句则括号中的内容会被转换成布尔类型(隐式转换)
switch 的 key 和 val 的比较是===绝对相等
switch 中的 break 用来中断程序
&&与,||或,!非
语句和表达式的区别
&&有一个是 flash 就是 flash,前面成立将值付给后面
|| 有一个是 true 就是 true ,前面不成立将值给后面
使用 ID 属性获取元素标签,用 document.getElementById(“标签的 ID 属性名”)
使用 class 属性获取元素标签,使用 document.getElementsClassName(“标签的 Class 属性名”)[第几个标签元素]
使用元素标签选择器,使用 document.getElementsTagName(“元素标签名”)[第几个元素标签"]
使用 querySelector 选择标签,使用方法用 document.querySeletor(用 class 名称)
使用 querySelectorAll 选择标签,使用方法使用 document.querySeletorAll(用 class 名称),与没有 All 不同的是这个选择的是数组
获取元素内部结构,用选择器选择出来标签,在用 innerHtml 可以拿到标签内部的标签,获取的时候能够获取结构,设置的时候能够识别结构
获取元素内部的文本,用选择器选择出来标签,在用 innerText 可以拿到标签内部的文本
给元素标签设置样式:’选择的标签属性.style.需要设置的样式名称 ’
查看标签样式,使用方法 style 但是只能查找到行内设置的样式
设置标签的类名,使用 className 可以获取和谁知标签的类名
值类型的赋予相当于是拷贝,引用类型等于指向(地址)
classList 查看类名列表,插入类名使用:类名.classList.add (“类名”)
移除类名使用:类名.classList.remove (“类名”)
在类名中移除或者添加使用:获取的标签.classLista.toggle(“类名”)
点击实践用 onclick:使用方法:选中的元素.onclick = function(){}
使用鼠标滑入功能 onmouseenter,鼠标滑出功能 onmouseleve
function a(){}
,函数表达式方式var a = function(){}
(function (){})()
(function(){
alert("自执行函数");
})();
(()=>{
alert("自执行函数");
})();
var result = index => index + 1;
var result = function(index) {
return index + 1;
}
var result = function(index) {
inner();
console.log(this.celler)
//指向的宿主环境是document
return index + 1;
}
var inner = function(){
console.log(inner.caller);
//指向的是result函数
console.log(arguments.callee);
//指向形参列表所在的函数inner
}
result();
for(var i =0 ; i < array.length ; i++){
console.log("这是第"i"个数组:"li[i]);
//依次打印出来数组的下标及每个数组元素
}
array[array.length] = "需要添加的数值"
for(var key in arr){
console.log(arr[key]);
//依次输出数组arr的每一个元素
}
array = [['1','2','3'],
['1','2','3'],
['1','2','3']]
var colors = ['red', 'pink'];
var res = colors.push('blue');
// 原数组
console.log(colors);//['red', 'pink', 'blue']
// 返回值
console.log(res);//
var colors = ['red', 'pink'];
var res = colors.pop();
// 原数组
console.log(colors);//['red']
// 返回值
console.log(res);//pink
var colors = ['red', 'pink'];
var res = colors.shift();
// 原数组
console.log(colors);//['pink']
// 返回值
console.log(res);//red
var colors = ['red', 'pink'];
var res = colors.unshift('blue', 'green');
// 原数组
console.log(colors);//['blue', 'green', 'red', 'pink']
// 返回值
console.log(res);//
var ary=[1,2,3];
var res=ary.reverse();
console.log(res);//[3,2,1];
console.log(ary);//[3,2,1];
- 如果没有传参数,只能对 10 以内的数进行排序
- 需要在 sort()括号内传入一个函数(回调函数)进行判断排序
var oldAry = [3, 1, 5, 11, 20];
var returnValue = oldAry.sort((a,b)=>a-b)
console.log(oldAry, returnValue);
var nums = [1, 2, 3, 4, 5, 6];
var res = nums.splice(0, 2);
console.log(nums);// [3, 4, 5, 6]
console.log(res);// [1,2]
var nums = [1, 2, 3, 4, 5, 6];
var res = nums.splice(3, 0, 7, 8, 9);
console.log(nums);//[1, 2, 3, 7, 8, 9, 4, 5, 6]
console.log(res);// []
var nums = [1, 2, 3, 4, 5, 6];
var res = nums.splice(0, 3, 7, 8, 9);
console.log(nums);//[7, 8, 9, 4, 5, 6]
console.log(res);// [1, 2, 3]
如果不传参数或者参数只有一个(0),表示将原数组复制一遍
var nums = [1, 2, 3, 4, 5, 6];
var res = nums.slice(1);
console.log(nums);//[1, 2, 3, 4, 5, 6]
console.log(res);// [2, 3, 4, 5, 6]
2. 如果有两个参数,slice()返回从开始索引到结束索引对应的所有元素
> 两个参数 表示开始下标到结束下标,包含开始,不包含结束
> 如果开始的位置大于结束的位置,返回值是空数组没有返回值
var nums = [1, 2, 3, 4, 5, 6];
var res = nums.slice(1, 5);
console.log(nums);//[1, 2, 3, 4, 5, 6]
console.log(res);// [2, 3, 4, 5]
concat()
var ary1 = [1, 2, 3];
var ary2 = [4, 5, 6];
var res = ary1.concat(ary2, "学校", "同学");
console.log(ary1);//[1, 2, 3]
console.log(res);//[1, 2, 3, 4, 5, 6, '学校', '同学']
toString()
var ary1 = [1, { a: 1 }, null, undefined, 3];
var res = ary1.toString();
console.log(ary1);//[1, {a:1},null, undefined, 3]
console.log(res)//1,[object Object]
join()
var ary1 = [1, 2, undefined, 3, { a: 1 }];
var res = ary1.join("|");
console.log(ary1);//[1, 2, undefined, 3, { a: 1 }]
console.log(res)// 1|2||3|[object Object]
eval(res) //==> eval 执行计算
includes()
var ary = [1,2,3,1,1,2,3];
var returnVlue = ary.indexOf(1,2);
console.log(returnVlue,ary);//3,原数组
var ary = [1,2,3,1,1,2,3];
var returnVlue = ary.lastIndexOf(1,2);
console.log(returnVlue,ary);//4,原数组
var ary = [1,2,3,1,1,2,3];
ary.forEach(function(item,value){
console.log(item,value);
})
var ary = [1,2,3,1,1,2,3];
var res = ary.map(function(item,value){
return item + 1;
})
console.log(res)
//[2,3,4,2,2,3,4]
数组去重会出现下标塌陷问题
var ary = [1, 2, 3, 1, 1, 2, 3];
for (var i = 0; i < ary.length - 1; i++) {
for (var j = i + 1; j < ary.length; j++) {
if (ary[i] == ary[j]) {
ary.splice(j, 1);
j--;
//解决下标塌陷问题,删除重复数组后将下标前移
}
}
}
console.log(ary);
var ary = [1, 2, 3, 43, 2, 1, 2, 3, 4, 11, 1, 1, 1, 1, 1, 1];
var obj = {};
for (var i = 0; i < ary.length; i++) {
var key = ary[i];
if (typeof obj[key] == "undefined") {
obj[key] = ary[i];
} else {
ary.splice(i, 1);
i--;
}
}
console.log(ary);
var ary = [1, 2, 3, 43, 2, 1, 2, 3, 4,11,1,1,1,1,1,1];
var obj = {};
var ary1 = [];
for (var i = 0; i < ary.length; i++) {
var key = ary[i];
obj[key] = ary[i];
//对象的属性名不能重复的特性
}
for(var i in obj){
ary1.push(obj[i]);
}
console.log(ary1);
var ary = [1,2,3,4,2,1,3,4,5,6];
var newAry = [];
for(var i in ary){
var item = ary[i];
if(newAry.indexOf(item) == -1){
newAry.push(ary[i]);
}
}
console.log(newAry);
var ray = [1, 4, 3, 2, 6, 5, 7];
var npm;
for (var i = 0; i < ray.length - 1; i++) {
for (var j = 0; j < ray.length - 1 - i; j++){
if(ray[j] > ray[j+1]){
npm = ray[i];
ray[i] = ray[j];
ray[j] = npm;
}
}
}
console.log(ray);
function total(num) {
if (num > 100) return 0;
return num + total(num + 1);
}
console.log(total(1));
var sty = "aewewerrer";
console.log(sty.charAt(0)); //a
var sty = "aewewerrer";
console.log(sty.charCodeAt(0)); //97
var sty = "aewewerrer";
console.log(sty.indexOf("e"));//1
console.log(sty.lastIndexOf("e"));//8
var sty = "aewewerrer";
console.log(sty.slice(3, 5));
var sty = "aewewerrer";
console.log(sty.substr(3, 4));//ewer
var sty = "aewewerrer";
console.log(sty.replace("aew", "yyy")); //yyyewerrer
作用:用符号将字符串分割成数组
var sty = "aewewerrer";
console.log(sty.split(""));
//[a,e,w,e,w,e,r,r,e,r]
var str = "https://www.baidu.com/s?tn=44004473_41_oem_dg&ie=utf-8&wd=%E5%B0%8F%E7%B1%B3%E5%AE%98%E7%BD%91";
function preat(str) {
var strSlice = str.split("?");
var strArry = strSlice[1].split("&");
var obj = {};
for (var i = 0; i < strArry.length; i++) {
strArry[i] = strArry[i].split("=");
obj[strArry[i][0]] = strArry[i][1];
}
return obj;
}
console.log(preat(str));
Math.abs():绝对值
console.log(Math.abs(-1)); // 1
Math.floor()向下取整,无论是正数还是负数都取小的
console.log(Math.floor(1.7));// 1
Math.ceil()向上取整,无论是正数还是负数取的都是大的
console.log(Math.floor(1.7)); // 2
Math.round()对小数四舍五入
console.log(Math.round(1.6)); // 2
Math.sqrt()开平方
console.log(Math.sqrt(9)); // 3
Math.pow(n,m)取幂
Math.PI()圆周率 π
Math.min()取最小值
Math.max()取最大值
math.random()取 0 到 1 不包含 1 的随机数
输出水仙花数
for (var i = 101; i < 1000; i++) {
var a = i % 10;
var b = Math.floor(i / 10 % 10);
var c = Math.floor(i / 100);
if (i == a * a * a + b * b * b + c * c * c) {
console.log(i)
}
}
var str = "smonsigjagidngoaenaoenbognaehuraehuabeiaerbiuaeerbngaegnagnkanoiawnoawnegoagnoianoiangoanegioniognaewonoagawhgineaonboaernb"; obj = {}; for (var i = 0; i < str.length; i++) { var key = str[i]; //判断数组中的属性名是否存在 if (typeof obj[key] === "undefined") { obj[key] = 1; //如果不存在就给属性值赋1 } else { obj[key] += 1; //如果存在就给属性值加一 } } var newMax = 0; var code = ''; //遍历对象查找字符出现最多的数 for (var k in obj){ //判断如果出现辞职大于newMax就将这一项付给newMax if(obj[k] > newMax){ newMax = obj[k]; code = k; } } console.log(`字符串str中最大的字符是${code}一共有${newMax}个`);
var arr = [4, 3, 1, 7, 8, 5, 34, 56, 78, 98, 13]; function sory(arry) { if (arry.length <= 1) return arry; var lest = Math.floor(arry.length / 2); var left = []; var reight = []; var itrm = arry[lest]; for (var i = 0; i < arry.length; i++) { if (i != lest) { if (arry[i] < arry[lest]) { left.push(arry[i]) } else { reight.push(arry[i]); } } } return sory(left).concat(itrm, sory(reight)); } console.log(sory(arr));
重点:回流必定会触发重绘,重绘不一定会触发回流。重绘的开销较小,回流的代价较高。
var divName = document.getElementsByClassName("box1")[1];
console.log(divName.getAttribute("name"))
let arry = [2, 3, 4, 53, 4, 5, 4, 32, 43, 54, 46, 578, 667]; function sort(arr = []) { for (let i = 0; i < arr.length; i++) { //索引i之前的那些项都是排好序的 let temp = arr[i]; let j = i - 1; while (j >= 0 && temp < arr[j]) { //判断arr[j]是否到了第一位以及判断temp和arr[j]的大小 arr[j + 1] = arr[j]; //对arr[j]进行位置调换 j--; } arr[j + 1] = temp; } return arr; } console.log(sort(arry));
nodeType:能够分辨节点到底是什么节点,只读
获取行内属性节点:getAttributeNode()
节点类:
function previouSibing(ele) {
let h2 = document.getElementsByTagName("h2")[0];
let per = h2.nextSibling;
while (per && per.nodeType != 1) {
per = per.nextSibling;
}
return per;
}
console.log(previouSibing());
元素类:
…在函数形参中是剩余运算符,在其他地方时展开运算符
ele.appendChild(“需要插入的元素”):把创建的元素元素添加到 ele 内部的最后一项
如果添加一个已经存在的选中标签,那么不会增加,只是移动到子元素末尾
var ul = document.getElementsByTagName("ul")[0];
var div = document.createElement("div");
ul.appendChild(div);
console.log(ul.innerHTML)
ele.insertBefore(div,a):给 ele 内部的 a 前面插入一个 div 标签
<div id="id1">
<p class="p1" id="p1">这是P1</p>
</div>
<script>
var div = document.getElementById("id1");
var p1 = document.getElementById("p1");
var odiv = document.createElement("div");
var returnDom = div.insertBefore(odiv, p1);
console.log(div);
</script>
createElement(“div”);创建一个 div 标签
createTextNode(“创建一个文本节点”):创建一个文本节点
cloneNode:把某一个节点进行克隆
cloneNode(true):(深克隆)把节点包含的所有内容进行克隆
<div id="id1">
<p class="p1" id="p1">这是P1</p>
</div>
<script>
var res = id1.cloneNode();
var res2 = id1.cloneNode(true);
console.log(res);
console.log(res2);
</script>
removeChild:移除元素
<div id="id1">
1111
<p class="p1" id="p1">这是P1</p>
</div>
<script>
id1.removeChild(p1);
console.log(id1);
</script>
ele.getAttibule(“xxx”):获取行内属性
ele.removeAttibule(“xxx”):删除行内属性
ele.setAttribute(“xxx”,“xxx”):设置行内属性
box.setAttribute("index", 1);
box.getAttribute("index");
box.removeAttribute("index");
console.log(box)
// 设置
// box["aa"] = 22;
// 获取
// box["aa"]
//移除
// delete box["aa"];
获取日期 new Date();
let time = new Date(); console.log(time); console.log(time.getFullYear()); console.log(time.getMonth()); console.log(time.getDate()); console.log(time.getHours()); console.log(time.getMinutes()); console.log(time.getSeconds()); console.log(time.getDay()); //Sat Mar 26 2022 16:14:02 GMT+0800 (中国标准时间) //2022 //2 //26 //16 //29 //55 //6
Date()括号中能够传入时间戳
time.getTime():是距离 1970 年 1 月 1 日的 00:00:00 的毫秒数
console.log(time.getTime(2022/12/3));
//1648283851978
new Date("时间戳");
就能转成公历日期setInterval(()=>{},1000)
//钟表函数 function times() { var apan = document.getElementsByTagName("span")[0]; let arry = ["日", "一", "二", "三", "四", "五", "六"]; setInterval(function () { let time = new Date(); let year = time.getFullYear(); let month = time.getMonth(); let date = time.getDate(); let hours = time.getHours(); let minutes = time.getMinutes(); let seconds = time.getSeconds(); let day = time.getDay(); apan.innerText = `现在是第${year}年${month + 1}月${date}日星期${arry[day]}${hours}时${minutes}分${seconds}秒`; }, 1000); } times();
function num(max, min) { return Math.floor(Math.random() * (max - min) + min); } function getCode() { var str = "0123456789"; var strin = ""; for (var i = 0; i < 4; i++) { strin += str[num(4, 0)]; } let div = document.getElementsByTagName("div")[0]; return div.innerHTML = strin; } getCode(); let timer = setInterval(() => { getCode(); }, 1000); setTimeout(() => { clearInterval(timer); }, 1000 * 10);
function fn(){
console.log(a);
return function f1(){
}
var a=3;
}
fn();
function f2(){
console.log("f2");
}
// 自执行函数在此处不进行变量提升
(function (){
console.log(a);// undefined, 照常进行变量提升
var a=3;
})();
"d" in window//判断window中有没有d
;const 声明的变量指针是不能改的
const num = 300; num = 200;
会报错
const num//会报错,没有初始值
但是在加入了块级作用域的时候 let 和 const 之后,在其被声明之前对块中的 let 和 const 进行 typeof 操作会报错
console.log(a, b);//undefined undefined
var a = 12,
b = 12;
function fn() { // undefined 12
console.log(a, b);
var a = b = 13;
console.log(a, b); // 13 13
}
fn();
console.log(a, b); // 12 13
全局栈内存页面关闭是会被释放,普通函数一般调用结束会被释放
闭包让你可以在一个内层函数中访问到其外层函数的作用域
闭包什么时候产生?
function fn(){
console.log(666);
setTimeout(()=>{
fn()
},1000)
}
fn();
$ ssh-keygen -t rsa -C "youremail@example.com"
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
在当前目录新建一个 Git 代码库
$ git init
新建一个目录,将其初始化为 Git 代码库
$ git init [project-name]
下载一个项目和它的整个代码历史
$ git clone [url]
添加指定文件到暂存区
$ git add [file1] [file2] ...
添加指定目录到暂存区,包括子目录
$ git add [dir]
添加当前目录的所有文件到暂存区
$ git add .
添加每个变化前,都会要求确认
对于同一个文件的多处变化,可以实现分次提交
$ git add -p
删除工作区文件,并且将这次删除放入暂存区
$ git rm [file1] [file2] ...
停止追踪指定文件,但该文件会保留在工作区
$ git rm --cached [file]
改名文件,并且将这个改名放入暂存区
$ git mv [file-original] [file-renamed]
提交暂存区到仓库区
$ git commit -m [message]
提交工作区自上次 commit 之后的变化,直接到仓库区
$ git commit -a
提交时显示所有 diff 信息
$ git commit -v
使用一次新的 commit,替代上一次提交
如果代码没有任何新变化,则用来改写上一次 commit 的提交信息
$ git commit --amend -m [message]
重做上一次 commit,并包括指定文件的新变化
$ git commit --amend [file1] [file2] ...
显示有变更的文件
$ git status
显示当前分支的版本历史
$ git log
显示 commit 历史,以及每次 commit 发生变更的文件
$ git log --stat
搜索提交历史,根据关键词
$ git log -S [keyword]
显示某个 commit 之后的所有变动,每个 commit 占据一行
$ git log [tag] HEAD --pretty=format:%s
显示某个 commit 之后的所有变动,其"提交说明"必须符合搜索条件
$ git log [tag] HEAD --grep feature
显示某个文件的版本历史,包括文件改名
$ git log --follow [file]
显示指定文件相关的每一次 diff
$ git log -p [file]
显示过去 5 次提交
$ git log -5 --pretty --oneline
显示所有提交过的用户,按提交次数排序
$ git shortlog -sn
显示指定文件是什么人在什么时间修改过
$ git blame [file]
显示暂存区和工作区的差异
$ git diff
显示暂存区和上一个 commit 的差异
$ git diff --cached [file]
显示工作区与当前分支最新 commit 之间的差异
$ git diff HEAD
显示两次提交之间的差异
$ git diff [first-branch]...[second-branch]
显示今天你写了多少行代码
$ git diff --shortstat "@{0 day ago}"
显示某次提交的元数据和内容变化
$ git show [commit]
显示某次提交发生变化的文件
$ git show --name-only [commit]
显示某次提交时,某个文件的内容
$ git show [commit]:[filename]
显示当前分支的最近几次提交
$ git reflog
列出所有本地分支
$ git branch
列出所有远程分支
$ git branch -r
列出所有本地分支和远程分支
$ git branch -a
新建一个分支,但依然停留在当前分支
$ git branch [branch-name]
新建一个分支,并切换到该分支
$ git checkout -b [branch]
新建一个分支,指向指定 commit
$ git branch [branch] [commit]
新建一个分支,与指定的远程分支建立追踪关系
$ git branch --track [branch] [remote-branch]
切换到指定分支,并更新工作区
$ git checkout [branch-name]
切换到上一个分支
$ git checkout -
建立追踪关系,在现有分支与指定的远程分支之间
$ git branch --set-upstream [branch] [remote-branch]
合并指定分支到当前分支
$ git merge [branch]
选择一个 commit,合并进当前分支
$ git cherry-pick [commit]
删除分支
$ git branch -d [branch-name]
删除远程分支
$ git push origin --delete [branch-name]
列出所有 tag
$ git tag
新建一个 tag 在当前 commit
$ git tag [tag]
新建一个 tag 在指定 commit
$ git tag [tag] [commit]
删除本地 tag
$ git tag -d [tag]
删除远程 tag
$ git push origin :refs/tags/[tagName]
查看 tag 信息
$ git show [tag]
提交指定 tag
$ git push [remote] [tag]
提交所有 tag
$ git push [remote] --tags
新建一个分支,指向某个 tag
$ git checkout -b [branch] [tag]
下载远程仓库的所有变动
$ git fetch [remote]
显示所有远程仓库
$ git remote -v
显示某个远程仓库的信息
$ git remote show [remote]
增加一个新的远程仓库,并命名
$ git remote add [shortname] [url]
取回远程仓库的变化,并与本地分支合并
$ git pull [remote] [branch]
允许不相关历史提交,并强制合并
$ git pull origin master --allow-unrelated-histories
上传本地指定分支到远程仓库
$ git push [remote] [branch]
强行推送当前分支到远程仓库,即使有冲突
$ git push [remote] --force
推送所有分支到远程仓库
$ git push [remote] --all
恢复暂存区的指定文件到工作区
$ git checkout [file]
恢复某个 commit 的指定文件到暂存区和工作区
$ git checkout [commit] [file]
恢复暂存区的所有文件到工作区
$ git checkout .
重置暂存区的指定文件,与上一次 commit 保持一致,但工作区不变
$ git reset [file]
重置暂存区与工作区,与上一次 commit 保持一致
$ git reset --hard
重置当前分支的指针为指定 commit,同时重置暂存区,但工作区不变
$ git reset [commit]
重置当前分支的 HEAD 为指定 commit,同时重置暂存区和工作区,与指定 commit 一致
$ git reset --hard [commit]
重置当前 HEAD 为指定 commit,但保持暂存区和工作区不变
$ git reset --keep [commit]
新建一个 commit,用来撤销指定 commit
后者的所有变化都将被前者抵消,并且应用到当前分支
$ git revert [commit]
暂时将未提交的变化移除,稍后再移入
$ git stash
$ git stash pop
1、配置语法:
以斜杠“/”开头表示目录;
以星号“*”通配多个字符;
以问号“?”通配单个字符
以方括号“[]”包含单个字符的匹配列表;
以叹号“!”表示不忽略(跟踪)匹配到的文件或目录;
此外,git 对于 .ignore 配置文件是按行从上到下进行规则匹配的,意味着如果前面的规则匹配的范围更大,则后面的规则将不会生效;
2、示例:
(1)规则:fd1/*
说明:忽略目录 fd1 下的全部内容;注意,不管是根目录下的 /fd1/ 目录,还是某个子目录 /child/fd1/ 目录,都会被忽略;
(2)规则:/fd1/*
说明:忽略根目录下的 /fd1/ 目录的全部内容;
(3)规则:
/*
!.gitignore
!/fw/bin/
!/fw/sf/
说明:忽略全部内容,但是不忽略 .gitignore 文件、根目录下的 /fw/bin/ 和 /fw/sf/ 目录;
<script>
function Person(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
}
var person = new Person("小明",12,0);
console.log(person);
特殊:只能用于引用数据类型,值类型不适用;
p1.hasOwnproperty(k)
//封装一个函数判断元素是否在公有属性上与hasOwnProperty作用相同
function P1(name, age) {
this.name = name;
this.age = age;
}
let p1 = new P1("one", 24);
P1.prototype.tos = "12";
Object.prototype.hasPubProperty = function (key) {
return (key in this) && !this.hasOwnProperty(key);
}
new 返回值:不是引用的话就是默认返回 this
f.call(xxx,a,b,c)//a,b,c是传给f的实参
,call 中的第一个参数是用来修改函数中的 this 指向,call 从第二个参数开始就是传给函数的实参function Person(name, age, sex) { this.name = name; this.age = age; this.sex = sex; } function myName(C, ...ages) { //new的特性是开辟一个新堆空间 let obj = {}; //让实例指向他的构造函数 obj.__proto__ = C.prototype; //改变this指向指向他开辟的空间obj let a = C.call(obj, ...ages); //判断构造函数执行结构,如果是引用类型就返回它执行结构,如果是值类型就返回this return typeof a == "object" ? a : obj; } let p1 = new Person("小康", 12, 1); let p2 = myName(Person, "小康", 12, 1)
var ary = [];
function myInstance(a, b) {
//判断a.prototype是否存在并且a.__proto__ !== b.prototype
while (a.__proto__&&a.__proto__ !== b.prototype) {
a = a.__proto__;
if (a.__proto__ === null) {
return console.log("没有")
}
}
return true;
}
console.log(myInstance(ary, Array));
console.log(myInstance(ary, Object));
[...arguments]
[].slice.call(div1)
先通过数组找到 slice 方法,通过 call 让这个 slice 执行,并且把其中的 this 变成类数组try{要执行可能会报错的代码}catch(形参){catch小括号中的形参对应的是上面运行错误信息;上面运行出错,就会走到这个catch,但是不会影响主体代码执行}
执行 try 中的代码如果报错就执行 catch 大括号中的代码let res1 = fn.bind(obj,1,2,3,4,5)
;var obj = Object.create(Array);//obj的__proto__指向Array
class 创造原型使用 eat(){},class 中没法添加值类型
class Person { //创造一个名为Person的类 constructor(name, age, sex) { //constructor是class规定的属性 console.log(arguments); //设置私有属性 this.name = name; this.age = age; this.sex = sex; } //私有属性height height = 1; //建立名为eat的原型,形参food eat(food){ console.log(`${food}`) } //static声明的是静态属性,指的是Person自己的属性 static qqq = 888; static ttt = 999; static yyy = 666; } let p1 = new Person("小孔", 12, 0); console.log(Person.qqq);//输出Person内置的静态属性qqq,它的实例是不能使用静态属性
//将obj私有属性都拼接起来 Object.prototype.qq = 123; var obj = { name: "大哥", age: 13 } function obje(one) { var h1 = document.getElementById("h1"); var a = Object.keys(one); var str = ""; a.forEach(itm => { str += `${itm}是${one[itm]};`; }); h1.innerText = str; } obje(obj)
对页面插入并且排序
var list = [{ name: "小红", age: 10 }, { name: "小红2", age: 120 }, { name: "小红3", age: 140 }, { name: "小红4", age: 105 }, { name: "小红5", age: 106 } ]; var ul = document.getElementsByTagName("ul")[0]; var but = document.getElementsByTagName("button"); class Proson { constructor(ul, but) { this.ul = ul; this.but = but; } butt(array) { this.one(array); this.but[0].onclick = () => { this.one(this.srop(array)); } this.but[1].onclick = () => { this.one(this.srop1(array)); } } one(array) { var str = ""; array.forEach(ele => { str += `<li>姓名是${ele.name};年龄是${ele.age};</li>` }); this.ul.innerHTML = str; } srop(array) { return array.sort((a, b) => { return a.age - b.age; }) } srop1(array) { return array.sort((a, b) => { return b.age - a.age; }) } } var but = new Proson(ul, but); but.butt(list)
js 中的数据类型
原始值类型(基本数据类型&值类型 0)
对象类型(引用数据类型)
非标准特殊对象 例如:new Number(1) -> 原始值类型对应的"对象类型"实例
函数对象 function
创造一个数字
num2 是 Number 类的一个实例,可以直接调用 Number.prototype 上的方法,从严格意义上讲,num1 不是 Number 类的实例(因为实例都是对象类型的),按理 num1 应该是无法调用 Number.prototype 上方法的,但是实际操作中,是可以调用的,所以也可以称 num1 是 Number 类的实例;
- num1 Number(null)默认会把原始值转换为对象,然后再去调用 toFixed 方法,我们把这种操作(“把原始值准换问实例对象”)称之为“装箱”!!
- num2+10 ->20 游览器会默认把实例对象转换为对应的原始值,然后再进行数学运算,这个过程称之为“拆箱”
parseInt/parseFloat 都是用来把其他值转换为数字:从字符串(传递的不是字符串,也要先转换为字符串)左侧第一个字符串开始查找,把找到的有效数字字符转换为数字,遇到一个非有效的,则停止朝招!一个都找不到,结构就是 NaN!
i++ / i-- / ++i / +i 一定是数学运算;i = i + 1; 可能是字符串拼接
+val 就是将 val 转化为数字
函数的创建
函数执行:
让“=”左侧出现和右侧值相类似的结构,然后快速取出某一部分的值,赋值给对应的变量
let arr = [1,2,3,4];
let [a,b] = arr;
console.log(a,b);//取出第一项和第二项1,2
let [,a,b] = arr;
console.log(a,b);//取出第二项和第三项2,3
let [a,...b] = arr;
console.log(a,b);//取出第一项付给a,剩余全部付给b,a = 1, b =[2,3,4]
let arr1 = [10];
let [a,b = 0] = arr1;
console.log(a,b); //给b赋默认值
谷歌浏览器:blink(webkit分支)
火狐:Gecko
.....
==============
真实项目开发,我们使用ES6语法,如果需要兼容 IE(>=IE10),我们需要基于 babel 模块,把ES6的语法转换为ES5....
https://babeljs.io/
arr.forEach((item,index)={})
for(let i = 0 ; i < arr.length;i++){}
var reg = /1/ //字面量 /元字符/ 定义一个规则:字符串中得有1
var reg2 = new RegExp('1') //构造函数
reg.test('aadfawaewaewfe')
字符串中的转义,就是把字符串中有特殊含义的字符转成字符串本身(不代表任何含义)
特殊的元字符:
var reg = /d/ //定义一个规则:字符串中得有d
var reg1 = /^1/
var reg2 = /1$/
var reg11 = /21$/
规则是:字符串必须是 1 结尾而且还是得"这个"1 前面必须是 2在[]中的.代表.本身
/^(11|12)$/ //要不11要不12
正则的捕获:exec
str.replace(reg, function (a, b, c) {
//这个回调函数什么时候执行每当字符串中有匹配正则的时候,这个回调就会执行一次
//字符创中有多少匹配正则的部分这个回调函数就会执行多少次
//这个回调函数的参数第一项指的是大正则捕获的内容,后边都是小分组捕获的内容
obj[b] = c;
})
![E6995ZB%5~YT1}D89YAUTP](https://cdn.jsdelivr.net/gh/yangyongit/image/imageE6995ZB%5~YT1}D8
9YAUTP.png) 4. js
js: offset类 offsetTop offsetLeft offsetWidth offsetHeight offsetParent --offsetWidth:width+左右padding+左右border client类 clientTop clientLeft clientWidth clientHeight --clientWidth:width+左右padding scroll类 scrollTop scrollLeft scrollWidth scrollHeight --scrollWidth:若内容不溢出等同于clientWidth 一旦溢出了 左padding+内容的实际宽度
console.log(box.style.xxx
获取写在元素"行内"上的样式[特点:样式只有写在行内上才能获取]body.offsetParent === null
/* IntersectionObserver:ES6新增的一个内置类 + 不兼容IE浏览器 + new IntersectionObserver(callback) 创建它的一个实例:创建一个监听器,用来监听一个或者多个DOM元素和浏览器可视窗口的交叉状态和信息 + 当交叉状态「出现在可视窗口中、离开可视窗口」发生改变,都会触发监听器的回调函数callback执行 + 在回调函数中可以获取所有监听的DOM和可视窗口的交叉信息 */ let box1 = document.querySelector('#box1'), box2 = document.querySelector('#box2'); // 创建监听器 let ob = new IntersectionObserver((changes) => { /* 回调函数执行: + 创建监听器、且监听了DOM元素会立即执行一次(连续监听多个DOM只触发一次,但是如果监听是分隔开的,每新监听一个元素都会触发执行一次) + 当监听的元素和可视窗口交叉状态改变,也会触发执行「默认是“一露头”或者“完全出去”,会触发;当然可以基于第二个Options配置项中的threshold来指定规则;」 + threshold: [0] 一露头&完全出去 + ... + threshold: [1] 完全出现&出去一点 ---- changes:是一个数组,记录了每一个监听元素和可视窗口的交叉信息 + boundingClientRect:记录当前监听元素的getBoundingClientRect获取的值 + isIntersecting:true/false true代表出现在可视窗口中,false则反之 + target:存储当前监听的这个DOM元素对象 + ... */ console.log(changes); }, { threshold: [1] }); // 监听某个DOM元素和可视窗口的交叉状态改变;unobserve移除监听; ob.observe(box1); ob.observe(box2);
游览器底层渲染机制:当我们从服务器获取代码后,浏览器是如何把代码渲染为页面及相关效果的
CRP(关键渲染路径)性能优化法则:了解浏览器底层处理的具体步骤,针对每一个步骤进行优化
JS 种的同步和异步编程
进程和线程:一个进程中可能包含多个线程
游览器是多线程,当基于游览器打开一个页面(开辟一个进程),会有不同的线程同时去做多件事情
游览器底层渲染机制
CRP 优化技巧:
图片懒加载一定要处理:不要在第一次渲染页面的时候,让图片资源的请求去占用有有限的 HTTP 线程以及宽带资源,优先本着 CSS/JS 资源获取;当页面渲染完成后,再去根据图片是否出现在视口中,加载真实图片;
关于<script>的优化
- async 的特点是:只要 js 代码获取到,就会立即执行,不管书写的先后顺序,使用与 JS 之间不存在依赖的时候"谁先请求回来先执行谁"
- defer 的特点是:必须当代 GUI 以及所有设置 defer 的 JS 代码都获取到,在按照之前书写的顺序,依次渲染和解析,即实现了资源的异步获取,也可以保证 JS 代码之间的依赖关系!
加快 DOM TREE 的构建
加快 CSSOM TREE 的构建
操作 DOM 比较消耗性能:大部分性能都消耗在了"DPM 的重拍(回流)和重绘"
页面第一次渲染,必然会出现一次 Layout(回流)和 painting(重绘);第一次渲染完成之后
如果基于 JS 操作 DOM,那么前端性能优化必做的事情:减少 DOM 的重排(回流)
把获取演示的操作和修改样式的操作分离开
let str = '';
for(let i = 1; i <= 10 ; i++){
str += `<div>${i}</div>`;
}
document.body.innerHTML += str;
//会导致BODY原始结构中绑定的事件全部小时,所以此操作适用于:原始容器中没有任何内荣,我们把新的内容插入进去
let frg=document.createDocumentFragment();//创建文档碎片:装DOM元素的容器
for( let i = 1 ; i <= 10 ; i++){
let divBox = document.createElement('div');
divBox.innerText = i;
frg.appendChild(divBox); //最后统一把文档碎片中所有内容放在body末尾,引发一次重排
}
<h1 data-h1 = 'a'><\h1>
,xxx.dataset.h1 == ‘a’;document.documentElement.offsetTop = 0
,现在游览器刷新会记录刷新之前的位置,使用这段代码不能回到游览器顶部 let timer = null;
inp.oninput = function () {
//oninput 当文本框的内容发生改变的时候执行这个函数
clearTimeout(timer);
timer = setTimeout(() => {
console.log(this.value);
fetch("./data.json");
}, 1000);
};
let throttle = (fn, delay) => {
let flag = true;
return function () {
if (!flag) return;
flag = false;
setTimeout(() => {
flag = true;
}, delay);
fn();
};
};
节流最多应用在 scroll 事件和 touchmove 事件
防抖的应用场景一个是按键的连续点击,另一个是 input 的连续输入
如果只想调用失败后的处理方法,可以. then(null,error),可以在第一个函数位置传个 null,它等同于调用 catch 方法:. catch(error)
jscript; // 创建一个任务对象,该任务立即进入 pending 状态 const pro = new Promise((resolve, reject) => { // 任务的具体执行流程,该函数会立即被执行 // 调用 resolve(data),可将任务变为 fulfilled 状态, data 为需要传递的相关数据 // 调用 reject(reason),可将任务变为 rejected 状态,reason 为需要传递的失败原因 }); pro.then( data => { // onFulfilled 函数,当任务完成后,会自动运行该函数,data 为任务完成的相关数据 }, reason => { // onRejected 函数,当任务失败后,会自动运行该函数,reason 为任务失败的相关原因 } );
后续处理也是一个任务
若没有相关的后续处理,新任务的状态和前任务一致,数据为前任务的数据
若有后续处理但还未执行,新任务挂起。
若后续处理执行了,则根据后续处理的情况确定新任务的状态
方法名 | 含义 |
---|---|
Promise. resolve(data) | 直接返回一个完成状态的任务 |
Promise. reject(reason) | 直接返回一个拒绝状态的任务 |
Promise. all(任务数组) | 返回一个任务 任务数组全部成功则成功 任何一个失败则失败 |
Promise. any(任务数组) | 返回一个任务 任务数组任一成功则成功 任务全部失败则失败 |
Promise. allSettled(任务数组) | 返回一个任务 任务数组全部已决则成功 该任务不会失败 |
Promise. race(任务数组) | 返回一个任务 任务数组任一已决则已决,状态和其一致 |
let arry = [
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
];
console.log(arry.flat()); //[1,2,3,1,2,3,1,2,3];
有了 Promise,异步任务就有了一种统一的处理方式
有了统一的处理方式,ES 官方就可以对其进一步优化
ES7 推出了两个关键字async
和await
,用于更加优雅的表达 Promise
async 关键字用于修饰函数,被它修饰的函数,一定返回 Promise
async function method1() { return 1; // 该函数的返回值是Promise完成后的数据 } method1(); // Promise { 1 } async function method2() { return Promise.resolve(1); // 若返回的是Promise,则method得到的Promise状态和其一致 } method2(); // Promise { 1 } async function method3() { throw new Error(1); // 若执行过程报错,则任务是rejected } method3(); // Promise { <rejected> Error(1) }
await
关键字表示等待某个 Promise 完成,它必须用于async
函数中
async function method() {
const n = await Promise.resolve(1);
console.log(n); // 1
}
// 上面的函数等同于
function method() {
return new Promise((resolve, reject) => {
Promise.resolve(1).then(n => {
console.log(n);
resolve(1);
});
});
}
await
也可以等待其他数据
async function method() {
const n = await 1; // 等同于 await Promise. resolve(1)
}
如果需要针对失败的任务进行处理,可以使用try-catch
语法
async function method() {
try {
const n = await Promise.reject(123); // 这句代码将抛出异常
console.log("成功", n);
} catch (err) {
console.log("失败", err);
}
}
method(); // 输出: 失败 123
let p1 = new Promise((res, rej) => {
// res rej 是两个函数体,Promise 给的
// rej(777)把 p1 变成了 rejected(失败态)
// res(888)把 p1 变成了 fulfilled/resolved(成功态)
//res 不执行 rej 也不执行 pending(等待态)
// p1 一旦变成了 rejected 或者 fulfilled 那么就不会在去改变
//promise 的实例肯定能由三种状态:原始状态是 pending,成功态 resolved/fulfilled 失败态 rejected
//实例状态:只能由 pending 变成 fulfilled 或者 rejected;不能有 fulfilled 变成 rejected 或者 fulfilled
//该函数报错的时候实例状态也会变成 rejected
});
then 的第一个回调函数执行时机:实例状态由 pending 变成 fulfilled 的时候,then 的第一个回调函数的执行接收的实参:res 执行的时候传递的第一个参数
then 的第二个回调函数执行时机:实例状态由 pending 变成 rejected 的时候,then 的第二个回调函数的执行接收的实参:rej 执行的时候传递的第一个参数
catch 对应的回调函数什么时候还行!上面的实例出现失败态的时候
后面的 then 执行成功函数还是失败函数看上一个 then 对应的回调函数执行有没有出错,后边的 then 的成功回调函数的参数是由上一个 then 中的回调函数的返回值决定的
finally 对应的回调会在最后不管前面成功还是失败都会走 finally 对应的回调函数
promise 是 js 里面的内置类,promises 是为了方便异步开发,promise 实例有三个状态 pending/fulfilled/rejected
游览器是多线程,但是它只分配一个"JS 引擎线程"用来渲染和解析 js 代码,所以 JS 是单线程的!!
throw new Error;//手动抛出异常
JS 中也存在异步编程依托于浏览器多线程,在基于 EventLoop 事件循环机制处理的
游览器打开一个页面,除了开辟堆栈内存,还会默认创建两个队列
定时器到时间后也不一定能执行(设定的时间是其最快的执行时间):如果此时主线程被占用,则必须等主线程空闲下来,排在 EventQueue 中的定时器才可以执行
基于 JS 和定时器实现动画效果会存在问题
但是可以基于 window.requestAnimationFrame 实现动画
promise:ES6 新增的内置类(构造函数),用来规划异步编程代码,解决回调地狱问题
let p1 = new Promise([executor])
let p = new Promise(()=>{...})
resolve(‘ok’)->把实例 p 的状态修改为 fulfilled,值(成功结果)是’ok’
reject(‘no’)->把实 p 的状态修改为 rejected,值(失败原因)是’no’
let p2 = p1.then(onfulfilled,onrejected);
不论是 onfulfilled 还是 onrejected 执行(由 p1 状态决定),方法的执行决定了 p2 的状态和值
p1.then( value =>{
console.log('成功',value)
},reason => {
console.log('失败',reason)
})
then 链的穿透/顺延机制
p.catch(onrejected)等价与p.then(null,onrejected)
真实项目中:then 中一般只传递 onfulfilled[成功干什么],最后一个 catch;这样不论中间哪个环节创建了失败的实例,都会穿透至最后一个 catch;catch 不加,出现失败案例,控制台报"红",但是不影响其他代码执行!!
关于 Promise.all/any/race 第三个方法的研究
let p = Promise.all([promises]);
AJAX 的串行和并行:真实项目中发送 ajax 请求都是"采用异步编程"
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。