🔒 JavaScript知识点补充

javascript查漏补缺,一些零碎的知识点的补充

sublime正则替换的用法

store.js的使用

记得判断是否存在容器

1
2
website = store.get('容器1') || website;
//从容器1中取出website,如果存在就覆盖原始的website,如果不存在就使用原始的website

获取head和body

1
2
document.head
document.body

prompt的使用

弹出一个确认框。如果点击取消,则promote返回null,所以要做判断是否点击确定还是取消

键盘事件要加在document身上

键盘事件要加在document身上

1
document.onkeypress = fn1;

ev

1
2
3
xxx.onclick= function (ev) {
console.log(ev); //可以看到许多和ev有关的内容
}

ev.target

ev.key和ev.keyCode

ev.key直接获取按下哪个键
ev.keyCode获取键值

oImg.onerror

1
2
3
oImg.onerror = function (ev) {
ev.target.src = '//i.loli.net/2017/11/10/5a051fbc5e183.png';//如果网络图标下载出错就改用默认图标
}

open和location.href

1
2
3
4
5
6
open('//www.qq.com'); //默认新窗口打开
open('//www.qq.com', '_blank');//同上
open('//www.qq.com', '_self');//在当前窗口打开
location.href = '//www.baidu.com'//同上
语法糖:location = '//www.baidu.com

location 是一个hash对象,location.href 是它的一个属性。
在获取时,用location.href
在赋值时,可以用location=”//www.xxx” ,也可以用 location.href=”//www.xxx”,两者效果相同

函数封装

1
2
3
4
5
6
function tag(tagName, attr){ //tag('div', {id:'div1', className:'test'})
var ele = document.creatElement(tagName);
for (var key in attr) { //遍历attr里的所有键值对
ele[key] = attr[key]; //div.id=div1, div.className=test
}
return ele;

return多个时要用json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function init() {
var keys = [
['q','w','e','r','t','y','u','i','o','p'],
['a','s','d','f','g','h','j','k','l']
];
var website = {
'q': 'qq.com',
'w': 'weibo.com'
};
return {
'keys': keys,
'website': website
}
}
var keys = init().keys; //或写成init()['keys']
var website = init().website; //或写成init()['website']

三元运算

1
2
3
var n = 7;
var msg = '数字' + n + '是' + (n % 2 === 0 ? '偶数' : '奇数');
console.log(msg);

变量提升

所有的变量的声明语句var,都会被提升到代码的头部,这就叫做变量提升

1
2
3
4
5
6
7
8
console.log(a);//undefined
var a = 1;
等同于
var a; //var提升到头部,此时a = undefined
console.log(a);
a = 1;

js命名规范

js对大小写敏感,所以var avar A是不同的。
要求:
第一个字符,可以是任意 Unicode 字母(包括英文字母和其他语言的字母),以及美元符号($)和下划线(_)。
第二个字符及后面的字符,除了 Unicode 字母、美元符号和下划线,还可以用数字0-9。
中文是合法的标识符,可以用作变量名。

1
var 临时变量 = 1;

sitch语句。

多个if…else连在一起使用的时候,可以转为使用更方便的switch结构。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
switch (fruit) {
case "banana":
// ...
break;
case "apple":
// ...
break;
default:
// ...
}
每个case代码块内部的break语句不能少,否则会接下去执行下一个case代码块
var x = 1;
switch (x) {
case 1:
console.log('x 等于1');
case 2:
console.log('x 等于2');
default:
console.log('x 等于其他值');
}
// x等于1
// x等于2
// x等于其他值
上面代码中,case代码块之中没有break语句,导致一直执行下去

switch语句采用的是严格相等运算符(===),而不是相等运算符(==)

do…while 循环

  • while循环句末没有分号,而do…while 循环 句末必须要有分号
  • 不管条件是否为真,do…while都会执行一次语句
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    do {
    语句
    } while (条件);
    -----------------
    var x = 3;
    var i = 0;
    do {
    console.log(i);
    i++;
    } while(i < x);

break 语句和 continue 语句

  • break语句用于直接跳出代码块或循环、直接停止。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    for (var i = 0; i < 5; i++) {
    console.log(i);
    if (i === 3)
    break; //i==3时跳出去,停止该循环
    }
    // 0
    // 1
    // 2
    // 3
  • continue语句立即终止本次循环,并直接开始下一轮循环。

    1
    2
    3
    4
    5
    6
    7
    var i = 0;
    while (i < 100){
    i++;
    if (i % 2 === 0) continue;
    console.log('i 当前为:' + i);
    }

上面代码只有在i为奇数时,才会输出i的值。如果i为偶数,则直接进入下一轮循环。

如果存在多重for循环,不带label的break语句和continue语句都只针对最内层循环。

跳转标签(label)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
标签名:
语句
---------------
top:
for (var i = 0; i < 3; i++){
for (var j = 0; j < 3; j++){
if (i === 1 && j === 1) break top;
console.log('i=' + i + ', j=' + j);
}
}
// i=0, j=0
// i=0, j=1
// i=0, j=2
// i=1, j=0
上面代码为一个双重for循环,break命令后面加上了top标签,
满足条件时,直接跳出双层循环。
如果break语句后面不使用标签,则只能跳出内层循环,进入下一次的外层循环。
----------------------
continue语句也可以与标签配合使用。
here:
for (var i = 0; i < 3; i++){
for (var j = 0; j < 3; j++){
if (i === 1 && j === 1) continue here;
console.log('i=' + i + ', j=' + j);
}
}
// i=0, j=0
// i=0, j=1
// i=0, j=2
// i=1, j=0
// i=2, j=0
// i=2, j=1
// i=2, j=2
上面代码中,continue命令后面有一个标签名here,
满足条件时,会跳过当前循环,直接进入下一轮外层循环。
如果continue语句后面不使用标签,则只能进入下一轮的内层循环。

null和undefined

1
2
3
4
5
6
7
8
9
Number(null) // 0
5 + null // 5
null是一个表示“空”的对象,null转为数字时,自动变成0
---------------
Number(undefined) // NaN
5 + undefined // NaN
undefined是一个表示”此处无定义”的原始值,转为数值时为NaN

空数组([])和空对象({})对应的布尔值,都是true

1
2
3
4
5
6
7
8
9
if ([]) {
console.log('true');
}
// true
if ({}) {
console.log('true');
}
// true

js中的科学计数法

1
2
3
4
5
6
7
123e3 // 123000
123e-3 // 0.123
-3.1e+12 //-3100000000000
.1e-23 //1e-24
小数点后紧跟5个以上的零,
就自动转为科学计数法
0.0000003 // 3e-7

js会自动进制转换

默认情况下,JavaScript 内部会自动将八进制、十六进制、二进制转为十进制。

1
2
3
4
5
6
7
8
9
10
11
12
0xff // 255
0o377 // 255
0b11 // 3
----------
有前导0的数值会被视为八进制,
但是如果前导0后面有数字89,则该数值被视为十进制。
0888 // 888
0777 // 511

判断浏览器是否支持标签的某个属性

1
2
3
判断浏览器是否支持a标签的download属性
"download" in document.createElement('a');//true or false

获取移动端坐标

1
2
3
var ev = ev.touches[0];//获取第一个触摸点
var x = ev.clientX;
由于触摸屏支持多点触控,有好几个touches,所以不能通过ev.clientX获取坐标

移动端必须在ontouchstart时,ev.preventDefault();阻止屏幕的滚动

btoa将字符串转成base64

1
2
3
4
5
6
7
8
9
10
11
12
btoa('stage'); // c3RhZ2U=
atob将base64转回字符串
atob('c3RhZ2U='); // stage
不支持中文,要把中文转成base64,必须加入encodeURI()转码环节
btoa('你好') //报错
btoa(encodeURI('你好')) // JUU0JUJEJUEwJUU1JUE1JUJE
base64还原成中文需要decodeURI()解码
decodeURI(atob('JUU0JUJEJUEwJUU1JUE1JUJE')) //你好
注意,encode在中间环节,decode在最终环节

ev.target 和 ev.currentTarget

1
2
3
4
5
6
7
8
<a href="#" id="a">
<span>111</span>
</a>
a.onclick = function(ev){
console.log(ev.target) // <a href="#" id="a"><span>111</span></a>
console.log(ev.currentTarget) // <span>111</span>
}

a.href 和 a.getAttribute(‘href’)

1
2
3
4
a.onclick = function () {
console.log(a.href);//自动添加http协议
console.log(a.getAttribute('href'));// #about
}

ele.offsetTop() 和 window.scrollTo(x,y)

1
2
var posY = ele.offsetTop;
window.scrollTo(0,posY);

缓动效果

建议使用ev.currentTarget替代ev.target

过渡完成后执行某个函数

transitionend事件
该事件在 CSS 完成过渡后触发。

1
div1.addEventListener('transitionend', fn);

动画结束后执行某个函数

animationend事件
该事件在 CSS 动画结束播放时触发

1
div1.addEventListener("animationend", fn);

animationiteration 该事件在 CSS 动画重复播放时触发
animationstart 该事件在 CSS 动画开始播放时触发

切换到另一个页面时,定时器错乱的解决办法

页面失去焦点的意思时,当我们由当前页面切换(此处‘切换’不是指的链接跳转)到另一个页面时,当前页面就失去了焦点
,如果我很久才回到当前页面,若该页面中有定时器时(如我们用定时器做的图片轮播),图片就会出现空白,
出现该原因是,当当前页面失去焦点时,浏览器会减慢失去焦点页面的资源加载和运行,为获得焦点的页面提供更多的资源。
但是我们失去焦点时的页面的定时器还在按程序的规定运行,而浏览器的运行又跟不上,所以就出现空白或卡顿现象。

一旦切换到别的页面,然后重新切换回来时,由于浏览器切换页面js定时器会变缓慢,当重新切换到当前窗口之前变慢的定时器堆积在一起便开始疯狂执行,会出现定时器错乱。

这是因为浏览器本着节省内存的性质,当切换到其他页面时,常用系统页面的定时器不运动,但是动画依然排列,当切换回来的时候,动画加速运动,出现错误,在轮播图之类的页面经常会发生这样的情况。

解决方法:
通过浏览器的焦点事件去执行该js(我也是才知道window窗口也是有焦点事件的)

1
2
3
4
5
6
7
8
var timer=null;
window.onfocus=function(){
timer=setInterval(autoRun,1000);
}
window.onblur=function(){
clearInterval(timer);
}

更好的方法是监听visibilitychange

1
2
3
4
5
6
7
8
document.addEventListener("visibilitychange", function() {
if (document.hidden === true) {
clearInterval(timer);
} else {
timer = setInterval(slide, 2000);
}
});

如果您使用的是jQuery,在animate前加上 $(obj).stop(true,true); 可以解决

1
2
3
setInterval(function(){
$("div").stop(true,true).animate({"top":"-20px"})
},1000);

查看是否支持某个方法或属性

1
2
3
4
5
'onclick' in document // true
'onmouseover' in document // true
'hidden' in document // true

多重三目运算

1
2
3
4
var hidden = 'hidden' in document ? 'hidden' :
'webkitHidden' in document ? 'webkitHidden' :
'mozHidden' in document ? 'mozHidden' :
null;

点击页面其他地方关闭弹出层

  • 需要给document添加click事件,而不是body身上,因为body的区域并不是整个页面的宽高,而是与内部文档流的尺寸总和有关
  • 为了防止点击按钮的同时触发document事件,因此需要阻断冒泡
  • document的点击事件需要改写成节省内存的写法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    btn.onclick = function (ev) {
    popover.style.display = 'block';
    }
    document.onclick = function () {//添加到document上
    console.log(1); //浪费内存
    popover.style.display = 'none';
    }
    wrapper.onclick = function (ev) {
    ev.stopPropagation();//阻止冒泡
    }
    上面这种写法浪费内存,因为只要点击document就会触发它的click事件
    $('#btn').click(function() {
    $('#popover').show();
    $(document).one('click', function() {
    //在click事件里,给父级加上了另一个事件,这个事件会被立刻执行,因此需要给wrapper阻断冒泡,让它在被点击时才执行
    console.log(1); //只有弹出层show出来后,才会触发document的click事件,且只触发一次
    $('#popover').hide();
    });
    });
    //document的click事件加在了btn函数内部,它会在冒泡阶段直接执行,即使不点击document也会直接执行
    因此需要阻断冒泡
    $('#wrapper').click(function(ev) {
    ev.stopPropagation();
    });

图片加载成功或失败

图片加载成功时: onload
图片加载失败时:onerror

1
2
3
4
5
6
<img src="image.gif" onerror="alert('图片加载出错')">
<img src="logo.png" onload="success()">
function success(){
alert("图片加载完成");
}

用console.time获取代码运行时长

1
2
3
console.time();//标记代码开始时间
// 代码
console.timeEnd();//标记代码结束时间

form的提交监听的是form

将submit事件加在整个form上,而不是提交按钮上
这样用户按回车也能提交表单

1
form.onsubmit = fn;

Date对象的日期格式化

toLocaleString() 中国时间

1
2
var d=new Date();
var n=d.toLocaleString(); //2018/3/29 上午10:42:13


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Date() //中国时间
Date.now() //时间戳 1523521282634
var d = new Date();
d.toLocaleString() //中国时间
console.log(d); // 输出:Mon Nov 04 2013 21:50:33 GMT+0800 (中国标准时间)
console.log(d.toDateString()); // 日期字符串,输出:Mon Nov 04 2013
console.log(d.toGMTString()); // 国外时间,GMT格式,输出:Mon, 04 Nov 2013 14:03:05 GMT
console.log(d.toISOString()); // 国外时间,ISO格式,输出:2013-11-04T14:03:05.420Z
console.log(d.toJSON()); // 输出:2013-11-04T14:03:05.420Z
console.log(d.toLocaleDateString()); // 转换为本地日期格式,视环境而定,输出:2013年11月4日
console.log(d.toLocaleString()); // 转换为本地日期和时间格式,视环境而定,输出:2013年11月4日 下午10:03:05
console.log(d.toLocaleTimeString()); // 转换为本地时间格式,视环境而定,输出:下午10:03:05
console.log(d.toString()); // 转换为字符串,输出:Mon Nov 04 2013 22:03:05 GMT+0800 (中国标准时间)
console.log(d.toTimeString()); // 转换为时间字符串,输出:22:03:05 GMT+0800 (中国标准时间)
console.log(d.toUTCString()); // 转换为世界时间,输出:Mon, 04 Nov 2013 14:03:05 GMT+0800

console.log(1)的值是什么?

答案:打印出1,但是return的值是undefined

1
2
var result = console.log(1);
result //undefined

document.write()

1
document.write("<h1>Hello World!</h1><p>Have a nice day!</p>")

write() 与 writeln() 的区别:点击查看

打字机效果

方法一:

方法二:

前面2中的document.write方法不会覆盖前面的内容,而innerHTML会覆盖之前的内容,,此时需要用+=
innerHTML += result[n-1]方法:

innerHTML += .slice(n-1,n)方法:

滚动条始终拉到最底下

1
window.scrollTo(0,document.body.scrollHeight);

移动端触摸touch事件

1
2
3
当按下手指时,触发ontouchstart;
当移动手指时,触发ontouchmove;
当抬起手指时,触发ontouchend。

用setTimeout+延时递归实现setInterval

因为循环定时器的speed一旦设定就无法改变,如果想要实时改变定时器的速度,就要用setTimeout+延时递归实现setInterval

1
2
3
4
5
6
7
var n = 0;
setTimeout(function xxx(){
n++;
if(n>=10) return;
document.body.innerHTML = n;
setTimeout(xxx,duration);
},duration);

占位符的用法

1
2
var name = 'stage';
h1.innerHTML = h1.innerHTML.replace(/{{name}}/ig,name);

利用:empty实现Skeleton Screen(加载占位图/骨架屏)

输入框的value不能一开始赋值

1
2
3
4
5
6
7
8
9
<input type=text id=x>
var v = x.value;//不能这样!!因为一开始输入框里是空的
////////////
var x = document.getElementById('x');
btn.onclick=function(){
console.log(x.value); //value必须在输入了内核后才能取到
}

输入框内填入json格式(必须双引号!!)

1
2
3
4
<input type="text" id="x">
<button id="y">点我</button>
在输入框内填入: {"a":1,"b":2} //json中必须双引号
1
2
3
4
y.onclick=function (){
var data = x.value
console.log(JSON.parse(data))
}

翻转字符串

1
'12345'.split('').reverse().join('') // 54321

btoa()转成base-64编码

1
2
let encodedData = window.btoa("Hello, world"); // 编码【不支持中文】
let decodedData = window.atob(encodedData); // 解码

多态生成的元素绑定事件

将事件绑定到父元素,通过冒泡触发
当前元素用ev.target获取

1
2
3
4
5
6
父级.onclick=function(ev){
var x = ev.target.innerHTML;
console.log(x);
}
父级.appendChild('<div>hello</div>');

获取checkbox

1
document.querySelectorAll("input[type='checkbox']")

删除数据后,筛选出新数据

1
2
3
4
var datas = [{id:1,b:2},{id:2,b:2},{id:3,b:2}];
//假设将id为2的那一项删除
var newDatas = datas.filter(data => data.a !== 2);

i++与i+=1

1
2
3
4
5
6
7
8
let a = 1;
function add(n){
return n++;
}
let result = add(a);
result //1
//i++先返回原始值后,再自增;建议使用i+=1解决这个bug

getAttribute()

一般用于href和src的获取

1
<a href="./page1"></a>
1
2
3
4
let a = document.querySelector('a');
a.getAttribute('href'); //你在html里怎么写,得到的就是什么:./page1
a.href //完整路径:http://www.xxx.com/page1
-------------本文结束感谢您的阅读-------------