NaN
NaN是一个特殊的值,只有它唯一的一个非自反的值
NaN == NaN // false
利用它的特性可以判断NaN
function isNaN(el){
return el !== el
}
关于值的引用问题
不局限于数组,对象也是一样的
var a = [1,2,3];
var b=a;
console.log(a); //[1,2,3]
console.log(b); //[1,2,3]
b=[4,5,6];
console.log(a); //[1,2,3]
console.log(b); //[4,5,6]
var c=a;
c[0]=0;
console.log(a); //0,2,3
console.log(b); //4,5,6
console.log(c); //0,2,3
第一段代码块是简单的指向复制问题,b的指向指向a指向的地址
第二段代码块是为b重新指向另外一个栈内存的地址,而b本质上是指向a指向的堆内存,并不能改变a指向的地址
第三段代码块是因为c改变指向的堆内存的值,所以a指向的值本身也会发生变化,因为b的指向此时与a,c的指向不同,所以没有影响
function foo(x){
x.push(4);
console.log(x); //[1,2,3,4]
x=[4,5,6];
x.push(7);
console.log(7); //[4,5,6,7]
}
var a = [1,2,3];
foo(a);
console.log(a); //[1,2,3,4]
结合上述理解:
当实参a传入foo()中时,形参复制了a的指向地址,这时候,x.push(4)时,改变了地址内的值,所以a指向同样的值也会随之改变。
但是x=[4,5,6]时,x的指向地址改变,与a指向的地址不一致,就是说不管x的值怎么改变都无法影响a的变化
因为之前指向同样值的时候对值进行了修改,因此a = [1,2,3,4]
function foo(x){
x=4;
}
var a=2;
foo(a);
console.log(a) //2
function foo(x){
x.c=3
}
var a=2;
var b = new Number(a);
foo(b);
console.log(b.c) //3
第一段代码块是因为a是栈内存,形参只是简单的复制a的数值,并不会改变a的值,毕竟是栈内存,不会像堆内存一样有指向的问题
第二段就是堆内存问题了,需要注意的是new
Number()这段代码的含义在this绑定属于new绑定,new绑定它会创建一个新的对象并且对象的this绑定在它的构造函数上(但是字面量就不会创建对象了,所以字面量不算是一个对象,因此也不会有属性,复制了也是undefined)
id选择器与标签的小知识
var a=document.createElement("div");
typeof a;//"object"
Object.prototype.toString.call(a); //"[object HTMLDivElment]"
可以检查标签类型
<div id="foo"></div>
console.log(window.foo); //<div id="foo"></div>
id选择器会为全局对象创建一个同名的变量,该变量的值是所在标签
函数节流,函数防抖实现
函数节流是指定时间内只执行一次任务
实现:
function throttle(fn, interval = 300) {
let canRun = true;
return function () {
if (!canRun) return;
canRun = false;
setTimeout(() => {
fn.apply(this, arguments);
canRun = true;
}, interval);
};
}
函数节流是在频繁触发的情况下,只有超过指定时间的间隔才能再次执行任务
function debounce(fn, interval = 300) {
let timeout = null;
return function () {
clearTimeout(timeout);
timeout = setTimeout(() => {
fn.apply(this, arguments);
}, interval);
};
}