下面记录一些重要的js知识点,防止遗忘
(1)js中的函数声明提升,可以让函数调用先于函数声明语句,因为在代码执行之前会先读取函数声明
(2)childNodes属性要返回文本节点(3)以及元素节点(1),最好不使用,代替为children,firstNode和lastNode也有可能是文本节点
文本节点不一定有看得见的文本,换行符也算一个文本节点,如下图,div有3个子节点,头尾2个都是textNode
只有div和p紧紧相连才没有文本节点
class="d1">
s
(3)同上,要获取一个元素节点的前一个或者后一个节点的话,使用previousElementSilbling/nextElementSibling 来获取,如果用previousSibling则会获取到文本节点
(4)创建一个新元素方法:
var newElement = document.createElement(标签名)
document.body.appendChild(newElement)
(5)DOM事件:stopPropagation(),比较有用,用于当大div里有小div,且二者都有onclick,如果不在小div添加event.stopPropagation()则点击小div会先后触发2个div的onclick
(6)HTML5 canvas 画图像的要点:必须等待图像加载完成后再调用drawImage,否则图片不显示,
var image = document.images[0]; window.onload = function(){ drawingContext.drawImage(image,0,0,300,400); }
(7)html5中拖动滑块获取其值的方法(oninput)
range:type="range" id="range1" min="1" max="10" οninput="getValue()"/>
var r = document.getElementById("range1"); var p = document.getElementById('p'); function getValue(){ p.innerText = ((r.value / r.max)*100).toString()+"%"; }
(8)js将一个数组赋值给另一个数组: 不能直接var arrayB = arrayA,这只是多了个引用,其实2者都对应同一个数组,应该如下做:
var a = [1,2,3]; var b = a.slice(0); a.push(4); console.log(b.join()); console.log(a.join());
(9)js中提升的概念非常重要:所有的声明如函数和变量的声明都会被提升到作用域顶端,而函数表达式不会被提升,因为是赋值操作,另外函数优先于变量被提升
例子: console.log(b),会导致reference error 而console.log(b);var b = 2 输出 undefined
尽量避免在快内部声明函数,这会导致函数声明被提升到块作用域的顶部
var a =2 这一句话被编译器理解为var a; a = 2;前者只是声明,后者是赋值
(10)call apply方法解释,首先这2个方法都是Function原型里的,用法:functionName.call(thisObj,arg), call 和apply会将functionName这个函数的调用放到thisObj的上下文
里,改变this指向,2者区别是参数不同,apply参数是数组
//call apply var color = 'green'; function lqy(){ this.color = 'red'; } function sbw(){ this.color = 'blue'; } var o = {color:"blue"}; function showColor(){ alert(this.color); }
var lqy = new lqy()//实例化该函数
showColor.apply(lqy);//red showColor.call(sbw());//blue showColor.call(this);//green showColor.call();//green
(11)event: clientX 事件属性返回当事件被触发时鼠标指针向对于浏览器页面(或客户区)的水平坐标。可以用来计算拖放
(12)函数节流,比较重要,window.onresize函数会导致连续不断的执行其中的代码,性能损耗严重,所以需要设定最小间隔时间来执行代码
这样当等待500ms后才会执行该函数,如果在小于500ms间隔内改变窗口大小都不会触发该函数,因为该函数未执行,所以直接clear掉然后再
添加新的settimeout,继续等待500ms
function throttle(method,context){ clearTimeout(method.tId); method.tId=setTimeout(function(){ method.call(context); },500); }
(13)区分ie,注意ie 11要特殊处理
var nav = navigator.userAgent; //区分是ie还是不是ie,ie11不支持 if(!+[1,]){ alert("ie < 11"); } else if(nav.indexOf('Trident') > -1 && nav.indexOf("rv:11.0") > -1){ alert('ie == 11'); } else{ alert("not ie");
}
(14) 快速将日期转为数值
var t = +new Date(),也可以用valueOf
(15)如果要让链接点击不做任何事,可以如下做
(16)各种宽高一张图搞定
(17)脚本永不出错的方法: window.onerror = function(e){return true;}
(18)使用!!variable 可以把变量转化为bool值
(19)undefined null NaN的区别:
首先,null 和 undefined是基本的6种主要类型之一,NaN(Not a Number)是一种特殊的数字,typeof(NaN)为Number
undefined 表示声明了变量未赋值或者引用对象不存在的属性时会出现undefined提示
null表示空,但不为0,可以显式给变量赋值null清空变量,null==undefined但不全等
而NaN表示减,乘,除 运算结果不为数字的后果,比如5-"a"表示为NaN,其中NaN不等于自己,因为是一个范围
(20)delete操作符,很蛋疼,记住以下几点
1,最常用来删除对象中的属性,如 var a = {b:1} ; delete a.b,返回true
2,用var声明的变量和函数无法删除
3,全局变量可以删除,比如 a=2,然后delete a是可以的
(21)想让一个对象不可变,可以调用Object.defineProperty方法或者Object.freeze或者Object.seal
(22)检测一个属性是否存在于对象中,不能用object.property == undefined来 判断,因为有可能其值就是undefined
方法有2种,第一是用in,propertyName in Object ,注意propertyName是字符串,这个会检查当前对象以及其原型链是否有属性
第二种是hasOwnProperty,这个方法只会检查当前对象是否有属性
(23) in操作符可以检查属性名是否存在对象中,但数组要小心,数组的属性名是下标0,1,2....不是其value,而对象属性名则是key
另外遍历对象的顺序是不确定的,数组是确定的
(24)全等操作符 和 相等操作符
== 比较时要转换为数值,例如"55" == 55 //TRUE,bool值转变为0或者1,字符串转为数字
=== 比较时不转换 上面为false
(25)var s = String('str') 这个s就是'str' ,值类型 而 var s = new String('str') 这个s是字符串对象,是引用类型
(26)js中字符串和数字相加都转化为字符串加,比如5+'2' = 52,结果是字符串注意了,而相减则变为数字相减,结果是数字
(27)arguments解释:Javascript中函数中的参数是以数组的形式保存的,所以在JavaScript中调用函数给函数传递的参数时,不会受到我们定义函数时设置的参数个数的限制。也就是说如果我们给一个函数定义了2个参数,我们传递的时候可以不传,可以传一个,也可以传两个,传三个...都可以,不会受函数参数个数的影响。arguments类似一个数组(但是不是真正的Array对象),同样可以像数组一样用方括号来访问它的每一个值,并用arguments.length来判断参数的个数。
(28)原型:在JavaScript中,我们创建一个函数A(就是声明一个函数), 那么浏览器就会在内存中创建一个对象B,而且每个函数都默认会有一个属性 prototype 指向了这个对象( 即:prototype的属性的值是这个对象 )。这个对象B就是函数A的原型对象,简称函数的原型。这个原型对象B 默认会有一个属性 constructor 指向了这个函数A ( 意思就是说:constructor属性的值是函数A )。
继承是通过原型链来继承
B.call(this)是类继承
(29)js中最大整数为Math.pow(2,53)-1 具体为9007199254740991,16位数字
(30)js for循环闭包问题最简单的解释:
var body = document.body, button, i; for(var i=0;i<5;i++){ button = document.createElement("button"); button.innerHTML = "button"+i; (function(i){ button.addEventListener("click",function(e){ alert(i) },false) })(i) body.appendChild(button) }上面不加闭包前 并不是传参,只是在函数内部引用了i,且都是同一个i,在执行时i已经变为5了,所以5个button都是5
加了闭包就变成传递函数参数了,传递的是值,复制的,不是引用,所以每个i都不同,注意这里立即执行了该匿名函数,否则函数里面的语句不会生效
(31)删除一个元素必须通过父元素的removeChild,所以node.parentNode.removeChild(node)
(32)getElementsByClassName("c1 c2 c3")参数可以是多个类组合,顺序不重要,而且可以匹配部分类名,就算元素带有更多类名也没关系
(33)ES6: 如果对复合变量声明为const,则要尤其小心,
如const obj = {} ; obj.a=5 可以改变对象属性,但是不能改变对象地址,再使用obj={}则报错,因为const仅仅让对象地址不可变,内容则是可变的
(34)ES6中,在最外层声明let a =1 则window.a = undefined 规定let声明的变量不属于全局对象属性,而var则是
(35)document.write()会重绘当前页面,而innerHTML不会,控制范围更精确
(36)js中提取子字符串最好用substring(start,end),返回新的字符串,start代表字符串开始位置,end代表结束位置加1,不指定end则直到末尾
(37)以下2个链接,第一个触发了click事件后不会触发点击事件,return false起作用了
(38) var b;
typeof b === 'undefined' //true 因为typeof返回字符串
b === undefined //true 这里不是字符串注意了
(39)统计代码用时
var times = 'loop'; console.time(times); for(var i=0;i<100000000;i++){ } console.timeEnd(times);
(40)数组中的索引也可以是字符串,但是这样不会增加数组长度,如果字符串可以被转为10进制,则例外 ,如
var a = [];
a['100'] = 1
console.log(a.length) // 101
(41)concat方法,将2者拼接在一起,支持数组和字符串,返回一个新的对象而不是在原来基础上修改,参数可以是多个数组或字符串
var s = s1.concat(s2)
(42)splice方法,arr.splice(pos,count,item) 该方法在pos位置开始删除元素,删除count个,用item来替代,item可以没有,直接修改原数组,不同于slice
(43)反转字符串,字符串是不可变的,也没有reverse方法,所以要如下处理
s.split('').reverse().join('')
(44)想要禁止表单元素的输入可以有2种方法,第一个是 第二个是利用js,获得焦点的同时失去焦点,好处是无法复制表单内容
var input = document.getElementById("input"); input.onfocus = function(){ input.blur(); }
(45)防止用户复制粘贴,其实是可以进行右键复制操作的,但是无法获取内容
var p = document.getElementsByTagName('p')[0]; p.onpaste = function(){ return false; } p.oncopy = function(){ return false; }
(46)动态定义正则表达式,注意参数没有斜线了
var name = 'sbw'; var reg = new RegExp("^("+name+")|("+name+")$","g"); alert(reg.test('eresbwer'))
(47)js中假值有如下几个,其余都是真值,可以用Boolean()来判断
undefined
null
''
NaN
0
false
(48)js中的一元运算符+,用来将字符串显示转化为数字
var c = '12'
typeof +c //number
(49)获取一个node的css样式一定要注意:
1,如果是内联样式,也就是
例外:如果没有内联样式,可以用node.style.width=xxx来写,这样就有内联样式了,后面就可以读取了
2,不是内联样式,可以用window.getComputedStyle(node,null).width获取宽度等样式,只读,写的话setAttribute('style',' .......'),
这个方法是获取最终计算的style结果
(46)settimeout函数传递参数写法:setTimeout(function(){yourFunc(arg1,arg2)},1000),用一层函数包起来
(47)判断bo参数为true的个数(参数不一定是true,比如为''1''也是true),利用隐式转换,true为1,false为0
//只有一个true,利用bool隐式转换 function onlyOneTrue(){ var sum=0; for(var i=0;ilength;i++){ sum+=Number(!!arguments[i]); } return sum===1; }
(48)js 中,|| 和 &&返回的是操作数,如4||5返回4, 0&&100返回0, 0||6返回6,而不是true和false
(49)重要的地方:判断一个值是否为true或者false最好这样用
if(a) 或者if(!!a)
不要这样用
if(a == true)或者if(a===true),因为5==true为false,这里会发生转换,true被转换为1,然后执行比较1==5,当然为false
(50) null==undefined 但是null!==undefined因为类型不同
(51)判断数值类型可以用 typeof(v) == 'number'来判断
(52)动态改变textarea高度,随着文字增多变高,注意要加px否则不起作用
(53)如果给html元素添加id属性,那么这个id会成为全局变量,这一点要小心使用
alert(d) //htmlObject
(54)一个html中有多个则后面的标签内的js代码可以调用前面标签中的方法和变量,这些标签共享一个global对象(window),但是函数声明提升却不起作用
(55)get,set方法的坑,不应该在get,set方法内使用改变属性值的操作语句,否则无限递归调用
get方法触发条件:当要获取age的值的时候
set方法触发条件:设置age值的时候
var obj = {}; Object.defineProperty(obj,'age',{ get:function(){ //此处会出现栈溢出,原因是在get方法内继续调用get方法 //obj.age --; return 1; }, set:function(value){ //此处会出现栈溢出,原因是在set方法内继续调用set方法 //age = value; } })
(56)判断字符串中是否存在另一个字符串,可用indexOf,search和正则等方法
(57)一个坑:js中只有一个删除节点的方法removeChild(),若想要删除所有子节点
如下写法不行,因为每次删除后索引要改变,可从后往前删除或者用while删除
for(var i=0,len=parent.children.length;i;i++){ citySelect.removeChild(citySelect.children[i]); }
(58)比较价格大小不能直接比较字符串大小,必须parseInt,因为'300' > '2000',首先按照首字符比较大小
(59)获取图片的宽高直接用var height = img.height; var width = img.width即可
(60)js中如果一个函数定义了一个bool参数,但是不传参,则参数默认为false,因为默认是undefined,等于false
(61)Array.splice(arg1,arg2),其中arg1是要删除的位置,arg2是要删除的个数,有返回值,是包含被删除元素的数组,本来以为直接就是返回原数组,坑啊!
(62)js判断数组相等不能直接用==或者===,结果为false,因为数组是对象,而2个不同对象肯定不等,也不能用toString方法,
因为['1',2] 会和 [1,2]相等,也就是说无法辨别字符串和数字,应该用最原始的方法,比较每个值是否相同,用===比较
(63)js中toFixed方法返回的是字符串,不是小数(Number)记住了
(64)ES6中Set比较相等是用===来判断,所以2个对象肯定不同,如下,s的size为2,而不是1,更容易出错的是s.has([])为false,因为这3个[]根本不是同一个对象
var s = new Set(); s.add([]) s.add([]) alert(s.size)
(65)js中数组遍历方法有几种,假设数组为array
1,最原始的方法
for(var i=0;i console.log(array[i]) } 2,数组内置的forEach,但不能跳出循环 array.forEach(function(v){ console.log(v); }) 3,es6新增的for...of for(let v of array){ console.log(v) } 4,for....in,这个方法有缺点,一般用来遍历对象而不是数组 (66)一个获取指定元素style的通用方法,兼容各种浏览器
function getStyle(eleNode){
var style = null;
if(window.getComputedStyle){
style = window.getComputedStyle(eleNode,null);
}
else{
style = eleNode.currentStyle; //ie独有的方法
}
return style;
}