Open Wscats opened 7 years ago
写一段脚本,实现:当页面上任意一个链接被点击的时候,alert出这个链接在页面上的顺序号,如第一个链接则alert(1),依次类推。
var links = document.getElementsByTagName('a'); console.log(links); for (var i = 0; i < links.length; i++) { links[i].onclick = (function (i) { return function () { alert(i) } })(i) } //or var links = document.getElementsByTagName('a'); console.log(links); for (let i = 0; i < links.length; i++) { links[i].onclick = function (i) { alert(i) } }
创建”内置”方法:给String对象定义一个repeatify方法,该方法接收一个整数参数,作为字符串重复的次数,最后返回重复指定次数的字符串。
String.prototype.repeatify = function (num) { var str = ""; for (var i = 0; i < num; i++) { str += this; } return str; } console.log("laoxie".repeatify(4))
完成一个函数,接受数组作为参数,数组元素为整数或者数组,数组元素包含整数或数组,函数返回扁平化后的数组,如:[1,[2,[[3,4],5],6]] = > [1,2,3,4,5,6]。
var arr = [1, [2, 3, [4, 5, [6]]], 7]; var newArr = []; function getNewArr(arr) { for (var i = 0; i < arr.length; i++) { if (typeof arr[i] == "number") { newArr.push(arr[i]) } else { getNewArr(arr[i]) } } } getNewArr(arr)
假设现有一篇文章 var content = “…大量文字”,文章触及到一些敏感词[“wscat”,“yao”,“eno”,“6.1”]等,如何在文章中发现这些敏感词,并将背景置为红色或改变字体颜色标识出来。 var str = "6.1号,这是愉快的儿童节,我清晰地记得,愚蠢的yao牵着可爱的eno..."; var keyword = ["老谢", "老蓝", "千锋", "6.1"]; for (var i = 0; i < keyword.length; i++) { str = str.split(keyword[i]); str = str.join("<span style='color:red'>" + keyword[i] + "</span>") console.log(str) } document.getElementById('str').innerHTML = str; 不能使用定时器,实现5s刷新一次页面
假设现有一篇文章 var content = “…大量文字”,文章触及到一些敏感词[“wscat”,“yao”,“eno”,“6.1”]等,如何在文章中发现这些敏感词,并将背景置为红色或改变字体颜色标识出来。
var str = "6.1号,这是愉快的儿童节,我清晰地记得,愚蠢的yao牵着可爱的eno..."; var keyword = ["老谢", "老蓝", "千锋", "6.1"]; for (var i = 0; i < keyword.length; i++) { str = str.split(keyword[i]); str = str.join("<span style='color:red'>" + keyword[i] + "</span>") console.log(str) } document.getElementById('str').innerHTML = str;
不能使用定时器,实现5s刷新一次页面
定时自动刷新,content表示刷新间隔,单位为秒s,下面代码表示页面每隔三秒刷新一次
<meta http-equiv="refresh" content="3">
这种方法实现页面刷新有点投机取巧,这个标签作用是定时跳转,content第一个参数表示间隔时间,单位为秒,第二个参数表示目标网址,但是如果把第二个参数设为#,就会实现页面刷新
<meta http-equiv="refresh" content="3;url=#">
event.currentTarget和event.target的不同
可以发现,由于事件捕获和事件冒泡的存在,很多时候注册的事件监听者event.currentTarget并不是事件的触发者event.target,大部分时候事件可能是由子元素触发的,但是在捕获、冒泡的过程中被父级元素的事件监听器获取到了,注册监听事件的父级元素就是这种情况下event.currentTarget,而事件触发者也就是子元素就是event.target
event.currentTarget
event.target
<head> <meta charset="utf-8"> <title>菜鸟教程(runoob.com)</title> </head> <body> <p>该实例使用 addEventListener() 方法在按钮中添加点击事件。 </p> <button id="myBtn">点我</button> <p id="demo"></p> <script> var btn = document.getElementById("myBtn"); btn.addEventListener("click", function displayDate1(e) { console.log('按钮注册点击事件'); console.log("e.currentTarget", e.currentTarget); console.log("e.target", e.target); console.log("this", this) }); document.body.addEventListener("click", function displayDate1(e) { console.log('body注册点击事件'); console.log("e.currentTarget", e.currentTarget); console.log("e.target", e.target); console.log("this", this) }); </script> </body> </html>
css加载会阻塞DOM树渲染吗?
不会
这可能也是浏览器的一种优化机制。因为你加载css的时候,可能会修改下面DOM节点的样式,如果css加载不阻塞DOM树渲染的话,那么当css加载完之后,DOM树可能又得重新重绘或者回流了,这就造成了一些没有必要的损耗。所以我干脆就先把DOM树的结构先解析完,把可以做的工作做完,然后等你css加载完之后,在根据最终的样式来渲染DOM树,这种做法性能方面确实会比较好一点,摘自css加载会造成阻塞吗?
defer和async的区别
<script src="script.js"></script>
没有 defer 或 async,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该 script 标签之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。
<script async src="script.js"></script>
有 async,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。
<script defer src="myscript.js"></script>
有 defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。defer和async的区别
遍历一个某一元素下的所有子元素(包括子元素的子元素)的方法,打印出所有子元素的ID
假设要遍历document.body
document.body
var allNodes = []; function getChildNode(node) { //先找到子结点 var nodeList = node.childNodes; for (var i = 0; i < nodeList.length; i++) { //childNode获取到到的节点包含了各种类型的节点 //但是我们只需要元素节点 通过nodeType去判断当前的这个节点是不是元素节点 var childNode = nodeList[i]; //判断是否是元素结点 if (childNode.nodeType == 1) { console.log(childNode.id); allNodes.push[childNode]; //childNode.style.border = "1px solid red"; getChildNode(childNode); } } } getChildNode(document.body); //getChildNode("某元素");
f(1)=1, f(1)(2)=2, f(1)(2)(3)=6, 设置一个函数输出一下的值
难点:打印和相加计算,会分别调用toString或valueOf函数,所以我们重写temp的toString和valueOf方法,返回a的值,这里测试的时候发现只要改写toString就可以了
toString
valueOf
function add(a) { var temp = function (b) { return add(a + b); } temp.valueOf = temp.toString = function () { return a; }; return temp; } console.log(add(1)(2)); alert(add(1)(2)(3));
简单讲,在对对象(广义的,包括函数对象)进行+ - * / == > < >= <=运算时,会依次尝试调用私有toString私有valueOf原型toString原型valueOf,直到遇到返回基本类型(如数字或字符串)停止,这里可以参考实现语法的功能:var a = add(1)(2)(3); //6没看懂别人的代码
var temp = function () { var a = 1 + 2;//这里执行了加法所以会执行temp.toString方法 return temp; }; temp.toString = function () { return "wscats"; }; console.log(temp());
从图片可以看出来,当改写了toString后,既返回了函数,还打印出了结果
实现下面的函数new Test("test").firstSleep(3).sleep(5).eat("dinner")
new Test("test").firstSleep(3).sleep(5).eat("dinner")
具体可以参考链式调用
function Test(name) { this.task = []; let fn = () => { console.log(name); this.next(); } this.task.push(fn); setTimeout(() => { this.next(); }, 0) return this; } Test.prototype.firstSleep = function (timer) { console.time("firstSleep") let that = this; let fn = () => { setTimeout(() => { console.timeEnd("firstSleep"); that.next(); }, timer * 1000) } this.task.unshift(fn); return this; } Test.prototype.sleep = function (timer) { console.time("sleep") let that = this; let fn = () => { setTimeout(() => { console.timeEnd("sleep"); that.next(); }, timer * 1000) } this.task.push(fn); return this; } Test.prototype.eat = function (dinner) { let that = this; let fn = () => { console.log(dinner); that.next(); } this.task.push(fn); return this; } Test.prototype.next = function (dinner) { let fn = this.task.shift(); fn && fn() } new Test("test").firstSleep(3).sleep(5).eat("dinner")
如何优化if...else语句
if...else
决策树和卫语句
const a = 3; //bad: if (a === 1) { console.log('a > 1'); } if (a === 2) { console.log('a > 2'); } if (a === 3) { console.log('a > 3'); } if (a === 4) { console.log('a > 4'); } // good: switch(a) { case 1: console.log('a = 1'); case 2: console.log('a = 2'); case 3: console.log('a = 3'); defaut: console.log('blablabla'); } const judgeMap = { 1: () => { console.log('a = 1') }, 2: () => { console.log('a = 2') }, 3: () => { console.log('a = 3') }, 4: () => { console.log('a = 4') } } judgeMap[a]();
三元表达式
const strength = (password.length > 7) ? 'Strong' : 'Weak';
position:sticky
不用JS情况写滑动到头部固定,参考杀了个回马枪,还是说说position:sticky吧
交换变量
let a; let b; [a, b] = [1, 2, 3];
https://dmitripavlutin.com/swap-variables-javascript/
以下表达式 (a== 1 && a ==2 && a==3)可以为真吗?
const a = { value: 0 } a.valueOf = function () { return this.value += 1 } console.log( a == 1 && a == 2 && a == 3 );
如果a是一个数组Array,在数组转换成字符串的时候,数组toString会隐含调用join()方法
const a = [1, 2, 3]; a.join = a.shift; console.log( a == 1 && a == 2 && a ==3 );
扩展:字符编码实现相同效果
var aᅠ = 1; var a = 2; var ᅠa = 3; console.log(aᅠ === 1 && a === 2 && ᅠa=== 3 );
https://stackoverflow.com/questions/48270127/can-a-1-a-2-a-3-ever-evaluate-to-true
https://www.jianshu.com/p/acf797bdbe98
变量提升
{ a = 1; function a() { }; a = 2; console.log(a); // 2 } console.log(a); // 1
但是比上面会复杂一点,因为还涉及到块作用域,因为函数写在块作用域里面,由于函数提升,它即能访问局部作用域,也能访问全局作用域,所以此时会在全局作用域和块级作用域都产生一个变量 a
JavaScript 执行到函数所在的那一句把局部变量的内容扔给外面的那个变量
即相当如下的代码:
let outera; { let innera; innera = function () { }; innera = 1; // function a() { }; outera = innera; // JavaScript 执行到函数所在的那一句把局部变量的内容扔给外面的那个变量 innera = 2; console.log(innera); // 2 } console.log(outera); // 1
定时自动刷新,content表示刷新间隔,单位为秒s,下面代码表示页面每隔三秒刷新一次
这种方法实现页面刷新有点投机取巧,这个标签作用是定时跳转,content第一个参数表示间隔时间,单位为秒,第二个参数表示目标网址,但是如果把第二个参数设为#,就会实现页面刷新
可以发现,由于事件捕获和事件冒泡的存在,很多时候注册的事件监听者
event.currentTarget
并不是事件的触发者event.target
,大部分时候事件可能是由子元素触发的,但是在捕获、冒泡的过程中被父级元素的事件监听器获取到了,注册监听事件的父级元素就是这种情况下event.currentTarget
,而事件触发者也就是子元素就是event.target
不会
这可能也是浏览器的一种优化机制。因为你加载css的时候,可能会修改下面DOM节点的样式,如果css加载不阻塞DOM树渲染的话,那么当css加载完之后,DOM树可能又得重新重绘或者回流了,这就造成了一些没有必要的损耗。所以我干脆就先把DOM树的结构先解析完,把可以做的工作做完,然后等你css加载完之后,在根据最终的样式来渲染DOM树,这种做法性能方面确实会比较好一点,摘自css加载会造成阻塞吗?
没有 defer 或 async,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该 script 标签之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。
有 async,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。
有 defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。defer和async的区别
假设要遍历
document.body
难点:打印和相加计算,会分别调用
toString
或valueOf
函数,所以我们重写temp的toString
和valueOf
方法,返回a的值,这里测试的时候发现只要改写toString
就可以了简单讲,在对对象(广义的,包括函数对象)进行+ - * / == > < >= <=运算时,会依次尝试调用私有
toString
私有valueOf
原型toString
原型valueOf
,直到遇到返回基本类型(如数字或字符串)停止,这里可以参考实现语法的功能:var a = add(1)(2)(3); //6没看懂别人的代码从图片可以看出来,当改写了toString后,既返回了函数,还打印出了结果
具体可以参考链式调用
决策树和卫语句
三元表达式
不用JS情况写滑动到头部固定,参考杀了个回马枪,还是说说position:sticky吧
https://dmitripavlutin.com/swap-variables-javascript/
如果a是一个数组Array,在数组转换成字符串的时候,数组toString会隐含调用join()方法
扩展:字符编码实现相同效果
https://stackoverflow.com/questions/48270127/can-a-1-a-2-a-3-ever-evaluate-to-true
https://www.jianshu.com/p/acf797bdbe98
但是比上面会复杂一点,因为还涉及到块作用域,因为函数写在块作用域里面,由于函数提升,它即能访问局部作用域,也能访问全局作用域,所以此时会在全局作用域和块级作用域都产生一个变量 a
JavaScript 执行到函数所在的那一句把局部变量的内容扔给外面的那个变量
即相当如下的代码: