(1)基本数据类型
number,string,boolean,null,undefined,symbol以及未来ES10新增的BigInt(任意精度整数)七类。
引用数据类型(Object类)有常规名值对的无序对象{a:1},数组[1,2,3],以及函数等。
number.toFixed()精度丢失----二进制浮点数表示法并不能精准表示十进制分数!JS采用二进制表示法,可以精确地表示二进制分数(1/2),但不能表示十进制分数(1/10)和像0.1这样的小数。
Math.round()四舍五入正确
Math.pow(2,5)求2的5次幂
保留小数的正确操作:
function toFixed(number,fractionDigits){
var times = Math.pow(10, fractionDigits);
var roundNum = Math.round(number * times) / times;
return roundNum.toFixed(fractionDigits);
}
3==true 打印出什么
会打印出false,这里会将true转变成1。 1==true为true
Number 和 String 或者 Bool 类型比较,会对String 或者 Bool 类型进行ToNumber()转换
!!注意number转boolean时:!!0为false,!!1为true
箭头函数和function区别:
箭头函数是匿名函数,不能作为构造函数,不能使用new;
箭头函数不绑定arguments,取而代之用rest参数...解决;
箭头函数的this指向不变,一直指向定义时的上下文环境对象(指向定义时外层第一个普通函数的this, 当箭头函数外层没有普通函数时,它的this在严格和非严格模式都是指向window);function指调用自己的对象;
箭头函数没有原型属性;
箭头函数不能当做Generator函数,不能使用yield关键字
(2)变量及属性
1、实例属性和原型属性:JavaScript-实例属性与原型属性区别_一起的远方的博客-优快云博客
(3)判断元素是对象类型
1. typeof(根据对象在底层存储的二进制来判断类型, 在 JavaScript 中二进制前三位都为 0 的话会被判断为 object 类型, null 的二进制表示是全 0, 自然前三位也是 0, 所以执行 typeof 时会返回“object”)
判断字符串得到string,数字和NaN得到number,函数会得到function等,但是判断数组,对象和null时都会得到object
2. instanceof(原型链)
可以用来判断一个变量是数组还是对象,数组也是对象的一种,使用instanceof都会返回true,但是对象instanceof Array返回false
3. constructor
console.log(arr.constructor === Array); //true
console.log(arr.constructor === Object); //false
console.log(obj.constructor === Object); //true
4. Object.prototype.toString.call()
可以精准判断变量类型,它返回[object constructorName]的字符串格式,这里的constructorName就是call参数的函数名
var res = Object.prototype.toString.call(arr);
console.log(res); //[object Array]
var res2 = Object.prototype.toString.call(obj);
console.log(res2); //[object Object]
var res3 = Object.prototype.toString.call(a);
console.log(res3); //[object Number]
var res4 = Object.prototype.toString.call(b);
console.log(res4); //[object String]
var res4 = Object.prototype.toString.call(c);
console.log(res4); //[object Null]
var res5 = Object.prototype.toString.call(d);
console.log(res5); //[object Boolean]
var res6 = Object.prototype.toString.call(e);
console.log(res6); //[object Undefined]
var res7 = Object.prototype.toString.call(f);
console.log(res7); //[object Symbol]
5. 总结
判断简单数据类型可以用typeof,判断数组,对象使用instanceof,constructor和 Object.prototype.toString.call(),最好使用Object.prototype.toString.call(),更加精准
判断变量是不是数组的几个方法
var a=[];
a.constructor===Array //true
a instanceof Array === true //true
⚠️ 注意:以上方法在跨frame时会有问题,跨frame实例化的对象不共享原型
解决:
Object.prototype.toString.call(a) // "[object Array]"
Array.isArray(a) //true
(4)js对象的深拷贝
首推的方法简单有效,JSON.stringfy()和JSON.parse()即可搞定。但是这种简单粗暴的方法有其局限性。当值为undefined、function、symbol 会在转换过程中被忽略。。。所以,对象值有这三种的话用这种方法会导致属性丢失
var syb = Symbol('obj');
var person = {
name :'tino',
say: function(){
console.log('hi');
},
ok: syb,
un: undefined
}
var copy = JSON.parse(JSON.stringify(person))
2、当值为undefined、function、symbol 时
function deepCopy(obj) {
var result = Array.isArray(obj) ? [] : {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
if (typeof obj[key] === 'object' && obj[key]!==null) {
result[key] = deepCopy(obj[key]); //递归复制
} else {
result[key] = obj[key];
}
}
}
return result;
}
(5)循环
for循环里要跳出整个循环是使用break,但在数组中用forEach循环如要退出整个循环呢?使用break会报错,使用return也不能跳出循环:
第一种:使用try···catch捕获异常实现
第二种方法:使用arr.some()或者arr.every()替代
js数组循环常用的几种方法_JiaPeng366的博客-优快云博客
js的15种循环遍历,你掌握了几种?_诗人与黑客的博客-优快云博客_js 循环
(6)数组操作
去重
1. new Set()
ES6 新增了 Set 这一数据结构,类似于数组,但 Set 的成员具有唯一性。
function distinct(a, b) {
return Array.from(new Set([...a, ...b]))
}
2. for...of + Object
首先创建一个空对象,然后用 for 循环遍历
利用对象的属性不会重复这一特性,校验数组元素是否重复
function distinct(a, b) {
let arr = a.concat(b)
let result = []
let obj = {}
for (let i of arr) {
if (!obj[i]) {
result.push(i)
obj[i] = 1
}
}
return result
}
提取元素(同样适用于字符串):
slice(start,end)、splice(strt,end,index1,index2)
1、slice()方法
---可以用来从数组中提取指定元素
---该方法不会改变元素数组,而是将截取到的元素封装到一个新数组中返回
参数:
1.截取开始的位置的索引,包含开始索引,省略默认从索引0开始
2.截取结束的位置的索引,不包含结束索引,省略默认到末尾
-第二个参数可以忽略不写,此时会截取从开始索引往后的所有元素
-索引可以传递一个负值,如果传递一个负值,则从后往前计算
-1 倒数第一个
-2 倒数第二个
**字符串中的substring()方法也可以截取字符串,跟slice()类似,不同的是这个方法不能直接接受负值作为参数,如果传递了一个负值,则默认使用0
substr和substring
语法:substr(start [,length]) 第一个字符的索引是0,start必选 length可选
substring(start [, end]) 第一个字符的索引是0,start必选 end可选
相同点:当有一个参数时,两者的功能是一样的,返回从start指定的位置直到字符串结束的子串
不同点:有两个参数时
(1)substr(start,length) 返回从start位置开始length长度的子串
“goodboy”.substr(1,6); //oodboy
【注】当length为0或者负数,返回空字符串
(2)substring(start,end) 返回从start位置开始到end位置的子串(不包含end)
“goodboy”.substring(1,6); //oodbo
【注】:
(1)substring 方法使用 start 和 end 两者中的较小值作为子字符串的起始点
(2)start 或 end 为 NaN 或者负数,那么将其替换为0
2、splice() 方法
-可以用于删除数组中的指定元素
-使用splice()会影响到原数组,会将指定元素从原数组中删除,并将被删除的元素作为返回值返回
-参数:
第一个,表示开始位置的索引
第二个,表示删除的数量
第三个及以后。。可以传递一些新的元素,这些元素将会自动插入到开始位置索引前边
增减元素
push(),向数组的末尾添加一个或多个元素,并返回新的数组长度。原数组改变。
pop(),删除并返回数组的最后一个元素,若该数组为空,则返回undefined。原数组改变。
unshift(),向数组的开头添加一个或多个元素,并返回新的数组长度。原数组改变
shift(),删除数组的第一项,并返回第一个元素的值。若该数组为空,则返回undefined。原数组改变。
数组扁平化
使多维数组变成一维数组
1、递归版本如下:
function flatter(arr) {
if (!arr.length) return;
return arr.reduce(
(pre, cur) =>
Array.isArray(cur) ? [...pre, ...flatter(cur)] : [...pre, cur],
[]
);
}
// console.log(flatter([1, 2, [1, [2, 3, [4, 5, [6]]]]]));
2、迭代的思路
function flatten(arr) {
if (!arr.length) return;
while (arr.some((item) => Array.isArray(item))) {
arr = [].concat(...arr);
}
return arr;
}
// console.log(flatter([1, 2, [1, [2, 3, [4, 5, [6]]]]]));
3、ES6中的flat([depth])函数
depth可选,指定要提取的嵌套数组的深度,默认值1。当参数为Infinity时,相当于扁平化最深层次
arr.flat(Infinity);
4、reduce和concat
function myFlat(arr, depth) {
if (depth == 0) {
return arr;
}
return arr.reduce((res, value)=>{
if(Array.isArray(value)){
res=res.concat(myFlat(value, depth-1));
}else{
res=res.concat(value);
}
return res;
}, []);
}
var a = [1,2,3,[5,6,4, [8,9,10]]];
myFlat(a,1);
(7)点击事件阻止冒泡及默认行为
防止冒泡和捕获:w3c的方法是e.stopPropagation(),IE则是使用e.cancelBubble = true
当需要停止冒泡行为时,可以使用
function stopBubble(e) {
//如果提供了事件对象,则这是一个非IE浏览器
if ( e && e.stopPropagation )
//因此它支持W3C的stopPropagation()方法
e.stopPropagation();
else
//否则,我们需要使用IE的方式来取消事件冒泡
window.event.cancelBubble = true;
}
取消默认事件:w3c的方法是e.preventDefault(),IE则是使用e.returnValue = false;
javascript的return false只会阻止默认行为,而是用jQuery的话则既阻止默认行为又防止对象冒泡。
当需要阻止默认行为时,可以使用
//阻止浏览器的默认行为
function stopDefault( e ) {
//阻止默认浏览器动作(W3C)
if ( e && e.preventDefault )
e.preventDefault();
//IE中阻止函数器默认动作的方式
else
window.event.returnValue = false;
return false;
}
(8)修改元素属性:
* 使用jquery操作元素的css样式(获取、修改等等)
//1、获取和设置样式
$("#tow").attr("class")获取ID为tow的class属性
$("#two").attr("class","divClass")设置Id为two的class属性。
//2、追加样式
$("#two").addClass("divClass2")为ID为two的对象追加样式divClass2
//3、移除样式
$("#two").removeClass("divClass")移除 ID为two的对象的class名为divClass的样式。
$(#two).removeClass("divClass divClass2")移除多个样式。
//4、切换类名
$("#two").toggleClass("anotherClass") //重复切换anotherClass样式
//5、判断是否含有某项样式
$("#two").hasClass("another")==$("#two").is(".another");
//6、获取css样式中的样式
$("div").css("color") 设置color属性值. $(element).css(style)
//设置单个样式
$("div").css("color","red")
//设置多个样式
$("div").css({fontSize:"30px",color:"red"})
$("div").css("height","30px")==$("div").height("30px")
$("div").css("width","30px")==$("div").height("30px")
//7.offset()方法
//它的作用是获取元素在当前视窗的相对偏移,其中返回对象包含两个属性,即top和left 。
//注意:只对可见元素有效。
var offset=$("div").offset();
var left=offset.left; //获取左偏移
var top=offset.top; //获取右偏移
//8、position()方法
//它的作用是获取元素相对于最近的一个position样式属性设置为relative或者absolute的祖父节点的相对偏移,与offset()一样,它返回的对象也包括两个属性即top和left。
//9、scrollTop()方法和scrollLeft()方法
$("div").scrollTop(); //获取元素的滚动条距顶端的距离。
$("div").scrollLeft(); //获取元素的滚动条距左侧的距离。
//10、jQuery中的 toggle和slideToggle 方法,都可以实现对一个元素的显示和隐藏。区别是:
//toggle:动态效果为从右至左。横向动作。
//slideToggle:动态效果从下至上。竖向动作。
//比如想实现一个树由下至上收缩的动态效果,就使用slideToggle就ok了。
$('input').attr("readonly",true)//将input元素设置为readonly
$('input').attr("readonly",false)//去除input元素的readonly属性
$('input').attr("disabled",true)//将input元素设置为disabled
$('input').attr("disabled",false)//去除input元素的disabled属性
(9)Get与Post的区别
- GET在浏览器回退时是无害的,而POST会再次提交请求。
- GET产生的URL地址可以被Bookmark,而POST不可以。
- GET请求会被浏览器主动cache,而POST不会,除非手动设置。
- GET请求只能进行url编码,而POST支持多种编码方式。
- GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
- GET请求在URL中传送的参数是有长度限制的,而POST么有。GET方法提交的url参数数据大小没有限制,在http协议中没有对url长度进行限制,这个限制是特定的浏览器及服务器对他的限制
- 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
- GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。get提交数据还可能会造成CSRF攻击
- GET参数通过URL传递,POST放在Request body中。
(10)jQuery的deferred对象:
jQuery的回调函数解决方案;$.when的参数只能是deferred对象
$.ajax()操作完成后,如果使用的是低于1.5.0版本的jQuery,返回的是XHR对象,你没法进行链式操作;如果高于1.5.0版本,返回的是deferred对象,可以进行链式操作。
jQuery的deferred对象详解 - 阮一峰的网络日志
(11)javascript中的关键字this:
javascript中的关键字this_知其白,守其黑;和其光,同其尘。-优快云博客
面向对象语言中 this 表示当前对象的一个引用。
但在 JavaScript 中 this 不是固定不变的,它会随着执行环境的改变而改变。
1、在对象方法中, this 指向调用它所在方法的对象。
2、单独使用 this,它指向全局(Global)对象。
3、函数使用中,this 指向函数的所属者。
4、严格模式下函数是没有绑定到 this 上,这时候 this 是 undefined。
5、在 HTML 事件中,this 指向了接收事件的 HTML 元素。
6、apply 和 call 允许切换函数执行的上下文环境(context),即 this 绑定的对象,call() 和 apply() 方法可以将 this 引用到任何对象。
箭头函数 => 改变的并非把 this 局部化,而是完全不把 this 绑定到里面去
(12)js封装组件
1、js封装组件的原理:https://blog.youkuaiyun.com/sunshao904/article/details/95162104?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param(怎样用原生JS封装自己需要的插件,bootstrap是个借鉴)
jquery组件的扩展和封装(无界面css):JS组件系列——封装自己的JS组件,你也可以
另外,带界面css的组件:原生JavaScript实现一个简单的组件化Tab_超的博客-优快云博客(原生JavaScript实现一个简单的组件化Tab)
(13)节流和防抖:
TS vs RXJS 中的防抖和节流 - 知乎
防抖debounce: 当一个事件持续触发时,指定间隔时间内没有再触发该事件,事件处理函数才会执行。如果在间隔时间之内重新触发了该事件,则重新开始计时。
节流throttleTime: 当一个事件持续触发时,保证一定时间内只执行一次
区别:
函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。 比如在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。
(14)安全:XSS 和 CSRF
XSS 和 CSRF简述及预防措施_我的博客-优快云博客_csrf xss
(15)Dom节点类型
深入理解DOM节点类型第一篇——12种DOM节点类型概述 - 小火柴的蓝色理想 - 博客园
(16)如何解决前端跨域问题
通过nginx反向代理
采用nginx反向代理能很好的实现跨域,目前我的项目就是采用的这种方式。
先做以下假设:
我的服务器域名为 www.simple.com ip为:100.100.100.100
前端项目部署在100.100.100.100:80
后端项目部署在100.100.100.100:8080
那么为了实现跨域,我可以这么配置我的nginx。
https://www.simple.com => 100.100.100.100:80
https://www.simple.com/api => 100.100.100.100:8080
当前端项目要请求接口的时候,可以通过https://www.simple.com/api进行请求,完美跨域。
(17)项目部署
使用jenkins进行前端项目自动部署 - 小火柴的蓝色理想 - 博客园
(18) 页面加载优化(减少白屏时间)
webpack-analysis-plugin --- 减少打包体积--moment.js、懒加载模块
js异步加载
html5、css3
html5 有哪些新特性:
拖拽释放(Drag and drop) API
语义化更好的内容标签(header,nav,footer,aside,article,section)
音频、视频 API(audio,video)
画布(Canvas) API
地理(Geolocation) API
本地离线存储(localStorage) 长期存储数据,浏览器关闭后数据不丢失;
会话存储(sessionStorage),数据在浏览器关闭后自动删除
表单控件,calendar、date、time、email、url、search
新的技术 webworker, websocket, Geolocation
css3:
margin合并问题
在正常布局流中上下两个含有内容的div的margin会发生合并,合并后的margin值为相对大的值,当div内容为空时也会自动忽略其margin