前端常用代码片段(一)

var argArray = Array.prototype.slice.call(arguments);

大部分需要引入 jquery-1.9.1.min.js(兼容ie8)

1.回车触发事件的代码

 $(function(){$('#username').focus();//回车查询document.onkeydown = function(event) {var e = event || window.event || arguments.callee.caller.arguments[0];if (e && e.keyCode == 13) {$("#signIn").trigger('click');}};});

2.把对象格式的参数转成键值对,并以&分割

/*** 把对象格式的参数转成键值对,并以&分割* @param arr 要转换的对象参数* @returns {string}*/
function maiyaBuildParam(arr){var result = '';for(var key in arr){result += key + "=" + encodeURIComponent(arr[key]) + "&";}result = result.substr(0,result.length-1);return result;
}

3.去除表单内容两端的空格,设置cookie缓存,对象转成字符串

 function submitForm() {var param = {userName: $.trim($("#username").val()),password: $.trim($("#password").val())//userName: $("#username").val().trim(),//password: $("#password").val().trim()//ie8下边支持$.trim,   不支持$("#").val().trim()};$.ajax({type: "post",url: serverIp + "rest/login?" + Math.random() + "&" + BuildParam(param),   //这里传入一个随机数避免ie8缓存问题,下边cache对ie8无效//data: JSON.stringify(param),  //传入组装的参数//contentType: "application/json; charset=utf-8",cache: false,  //禁用缓存dataType: "json",success: function (result) {if(result.result_code === '1'){$.cookie('userinfo', JSON.stringify(result.data), { expires: 7 });window.location.href = "index.html";}else{alert('用户名或密码错误');}},error: function(msg) {alert(msg.message || '操作失败!');}})}

4.设置cookie,获取cookie

//设置cookie比,并将json数据源转成string$.cookie('userinfo', JSON.stringify(json), { expires: 7 });//获取cookie,并将返回的string格式数据解析成jsonJSON.parse($.cookie('userinfo'));//清除cookie$.cookie('userinfo',null);

项目示例

//设置cookie$.ajax({type: "post",url: serverIp + "rest/login?" + Math.random() + "&" + maiyaBuildParam(param),dataType: "json",success: function (result) {if(result.result_code === '1'){$.cookie('userinfo', JSON.stringify(result.data), { expires: 7 });window.location.href = "index.html";}else{alert('用户名或密码错误');}},error: function(msg) {alert(msg.message || '操作失败!');}})
//获取和清空cookieif(!$.cookie('userinfo')) {location.href="login.html";}$("#loginOut a").click(function () {$.cookie('userinfo',null);});var userinfo = JSON.parse($.cookie('userinfo'));if(userinfo) {var _src = userinfo.docPic ? userinfo.docPic : (userinfo.docSex == 2 ? 'images/women.png' : 'images/man.png');$('#userInfoImage').attr("src",_src)$('#username,#leftusername').html(userinfo.docName);$('#jobtitle').html(userinfo.docProfe);var docRole = userinfo.docRole == 0 && '医师' || '管理员';$('#loginuser').html(docRole);}if(userinfo.docRole == 0) {$('#menu-product').show();$('#menu-admin,#menu-tongji').hide();} else if(userinfo.docRole == 1) {$('#menu-product').hide();$('#menu-admin,#menu-tongji').show();}

说明:
jquery.cookie.js 只允许开发人员存入字符串,故用JSON.stringify(json)将json转换成string

补充:JSON.stringify与JSON.parse() [ 此类方法在低版本ie上需要引入json2.js ]

parse用于从一个字符串中解析出json对象,如
var str = '{"name":"huangxiaojian","age":"23"}'
JSON.parse(str)
-->
Object
age: "23"
name: "huangxiaojian"
__proto__: Object
注意:单引号写在{}外,每个属性名都必须用双引号,否则会抛出异常。stringify()用于从一个对象解析出字符串,如
var a = {a:1,b:2}
JSON.stringify(a)
--->
结果:"{"a":1,"b":2}"

5.三目运算的另一种写法

var docRole = userinfo.docRole == 0 && '医师' || '管理员';var _src = userinfo.docPic ? userinfo.docPic : (userinfo.docSex == 2 ? 'images/women.png' : 'images/man.png');
记得以前看过别人写的文章里提到有网易的面试题出现过区分 ||  &&联合使用时返回的结果,当时老记不住,现在有这个应该容易记了

6.时间格式化

使用方式

new Date().format('yyyy-MM-dd');  // "2017-02-18"new Date().format('yyyy-MM-dd hh-mm-ss');  //
"2017-02-18 04-41-08"
new Date().format('yyyy-MM-dd hh/mm/ss');  //
"2017-02-18 04/41/18"
new Date().format('yyyy-MM-dd HH/mm/ss');  //
"2017-02-18 16/42/30"new Date().format('yyyy-MM-dd E HH/mm/ss');//"2017-02-18 六 16/51/16"
new Date().format('yyyy-MM-dd EE HH/mm/ss');  //
"2017-02-18 周六 16/51/30"new Date().format('yyyy-MM-dd EEE HH/mm/ss');  //
"2017-02-18 星期六 16/51/77"

源码

Date.prototype.format = function (fmt) {var o = {"M+": this.getMonth() + 1, //月份"d+": this.getDate(), //日"h+": this.getHours() % 12 == 0 ? 12 : this.getHours() % 12, //12小时"H+": this.getHours(), //24小时"m+": this.getMinutes(), //分"s+": this.getSeconds(), //秒"q+": Math.floor((this.getMonth() + 3) / 3), //季度"S": this.getMilliseconds() //毫秒};var week = {"0": "日","1": "一","2": "二","3": "三","4": "四","5": "五","6": "六"};if (/(y+)/.test(fmt)) {fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));}if (/(E+)/.test(fmt)) {fmt = fmt.replace(RegExp.$1, ((RegExp.$1.length > 1) ? (RegExp.$1.length > 2 ? "星期" : "周") : "") + week[this.getDay() + ""]);}for (var k in o) {if (new RegExp("(" + k + ")").test(fmt)) {fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));}}return fmt;
}

7.获取输入日期所在周或者前后某周的周一

使用方式

new Date();//Sat Feb 18 2017 17:35:25 GMT+0800 (中国标准时间)getMonday( new Date(),-1);  //
Mon Feb 06 2017 17:40:45 GMT+0800 (中国标准时间)getMonday( new Date());  //Mon Feb 13 2017 17:34:34 GMT+0800 (中国标准时间)getMonday( new Date(),1);  //
Mon Feb 20 2017 17:34:43 GMT+0800 (中国标准时间)

源码

function getMonday(date, offset){var today=date || new Date();return new Date( today - ((today.getDay() ||7) -1  - (offset||0) *7 )  *864E5  );
}//改进,获取输入日期所在周或者前后某周的任意某天
function getWeekAnyday(weekday,offset,date){var today=date || new Date();return new Date( today - ((today.getDay() ||7) -(weekday||0)  - (offset||0) *7 )  *864E5  );
}

8.获取输入日期的前后某天日期

使用方式

new Date();//Sat Feb 18 2017 17:35:25 GMT+0800 (中国标准时间)getOneDayByDate(new Date() ,-2);  //Thu Feb 16 2017 18:20:39 GMT+0800 (中国标准时间)getOneDayByDate(new Date() ,2);  //Mon Feb 20 2017 18:20:49 GMT+0800 (中国标准时间)

源码

function getOneDayByDate(date, n) {var d = typeof date == 'string' && new Date(date) || date;d.setTime(d.getTime()+24*60*60*1000*n);//return d.getFullYear()+"-" + (d.getMonth()+1) + "-" + d.getDate();  //用于获取"2017-2-16"格式日期return new Date(d);
}

9.My97DatePicker使用

首先引入js

场景1:选择时间段,前者不能大于后者的时间,后者不能小于前者时间且不大于当天时间

  -

给input赋相差一个星期的初始值

 $("#datemin").val(getOneDayByDate(new Date(), -6).format('yyyy-MM-dd'));$("#datemax").val(thisDate());function thisDate() {var d = new Date();return d.format('yyyy-MM-dd');
}

10.刷新当前页面

//刷新当前页面
 location.reload();
//如果把该方法的参数设置为 true,那么无论文档的最后修改日期是什么,它都会绕过缓存,从服务器上重新下载该文档。这与用户在单击浏览器的刷新按钮时按住 Shift 健的效果是完全一样。

这是原生的方法

11. 判断元素是否在数组内

js方法

var arr = [1, 2, 3];
// js arr.indexOf(3)
var result1 = arr.indexOf(3); //返回index为2

jquery方法

var arr = [1, 2, 3];
// jquery $.inArray(3, arr)
var result = $.inArray(3, arr); //返回index为2

自定义方法

var arr = [1, 2, 3];
// 自定义 contains(arr, 3)方法
function contains(arr, obj) {//whilevar i = arr.length;while(i--) {if(arr[i] === obj) {return i;}}return -1;
}
var result1 = contains(arr, 3); //返回index为2

12.解析url中传递的参数

描述:解析ajax get方式传递的参数,
例如“https://www.zybuluo.com/mdedi...://www.zybuluo.com/static/editor/md-help.markdown”

1.方法一

使用方式

 $.getUrlParam('url'); //"https://www.zybuluo.com/static/editor/md-help.markdown"

源码

$.getUrlParam = function(name) {var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");var r = decodeURIComponent(window.location.search).substr(1).match(reg);if (r!=null) return unescape(r[2]); return null;
};

说明:此方式是将方法拓展到了jquery,也可以定义成方法

使用方式

  getUrlParam('url');  //"https://www.zybuluo.com/static/editor/md-help.markdown"
function getUrlParam(name) {var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");var r = decodeURIComponent(window.location.search).substr(1).match(reg);if (r!=null) return unescape(r[2]); return null;
};

2.方法二将携带的所有参数转化成json对象

使用方式

var urlParamsToJson= getUrlParamsToJson(); //Object {url: "https://www.zybuluo.com/static/editor/md-help.markdown"}

源码

function getUrlParamsToJson() {var url = location.href;var nameValue;var paraString = url.substring(url.indexOf("?") + 1, url.length).split("&");var paraObj = {};for (var i = 0; nameValue = paraString[i]; i++) {var name = nameValue.substring(0, nameValue.indexOf("=")).toLowerCase();var value = nameValue.substring(nameValue.indexOf("=") + 1, nameValue.length);if (value.indexOf("#") > -1) {value = value.split("#")[0];}paraObj[name] = value;}return paraObj;
};

13.封装折叠(兼容ie8)

html

  • 标题+

    内容
    很多内容
  • 标题+

  • 标题+

css

.Huifold .item{ position:relative}
.Huifold .item h4{margin:0;font-weight:bold;position:relative;border-top: 1px solid #fff;font-size:15px;line-height:22px;padding:7px 10px;background-color:#eee;cursor:pointer;padding-right:30px}
.Huifold .item h4 b{position:absolute;display: block; cursor:pointer;right:10px;top:7px;width:16px;height:16px; text-align:center; color:#666}
.Huifold .item .info{display:none;padding:10px}

js

jQuery.Huifold = function (obj, obj_c, speed, obj_type, Event,selected) {/*5个参数顺序不可打乱,分别是:相应区,隐藏显示的内容,速度,类型,事件*///1    只打开一个,可以全部关闭//2    必须有一个打开//3    可打开多个//4全部打开var selected = selected ||"selected";if (obj_type == 2) {$(obj + ":first").find("b").html("-");$(obj_c + ":first").show();}if (obj_type == 4) {$(obj).find("b").html("-");$(obj_c).show();}if (obj_type == 5) {$(obj).find("b").html("-");$(obj_c).hide();}$(obj).on(Event, function () {// console.log("11111");if ($(this).next().is(":visible")) {if (obj_type == 2) {return false;}else {$(this).next().slideUp(speed).end().removeClass(selected);$(this).find("b").html("+");}}else {if (obj_type == 3 || obj_type == 4) {$(this).next().slideDown(speed).end().addClass(selected);$(this).find("b").html("-");} else {$(obj_c).slideUp(speed);$(obj).removeClass(selected);$(obj).find("b").html("+");$(this).next().slideDown(speed).end().addClass(selected);$(this).find("b").html("-");}}});
};

调用

$(function(){$.Huifold("#mealContainer>.item>.title", "#mealContainer>.item>.info", "fast", 4, "click");});

14.封装tab页切换(兼容ie8)


html

选项卡一选项卡二自适应宽度内容一内容二内容三

css

.clearfix:after{content:"\20";display:block;height:0;clear:both;visibility:hidden}.clearfix{zoom:1}
.tabBar {border-bottom: 2px solid #222}
.tabBar span {background-color: #e8e8e8;cursor: pointer;display: inline-block;float: left;font-weight: bold;height: 30px;line-height: 30px;padding: 0 15px}
.tabBar span.current{background-color: #222;color: #fff}
.tabCon {display: none}

js


 

jQuery.Huitab = function (tabBar, tabCon, class_name, tabEvent, i, callback) {var $tab_menu = $(tabBar);// 锟斤拷始锟斤拷锟斤拷锟斤拷$tab_menu.removeClass(class_name);$(tabBar).eq(i).addClass(class_name);$(tabCon).hide();$(tabCon).eq(i).show();callback && callback(i);$tab_menu.on(tabEvent, function (event) {$tab_menu.removeClass(class_name);$(this).addClass(class_name);var index = $tab_menu.index(this).toString();$(tabCon).hide();$(tabCon).eq(index).show();callback && callback(index);event.stopPropagation();});
};

调用
 

$(function(){$.Huitab("#tabbarSonFirst>.tabBar span", "#tabbarSonFirst>.tabCon", "current", "click", "0", loadChart);});
// #tabbarSonFirst 父级id
// #tabbarSonFirst>.tabBar span控制条
// #tabbarSonFirst>.tabCon内容区
// current 选中tab样式
// click 事件 点击切换,可以换成mousemove 移动鼠标切换
// 1    默认第2个tab为当前状态(从0开始)
// callback 实现选中后再加载函数
function loadChart(i) {switch (i) {case '0'loopSportData();break;case '1'loopMealData();break;case '2':loadBloodPressureChart();break;default:break;}
}


 

15.正则校验Excel

 var reg = /^.*\.(?:xls|xlsx)$/i;//文件名可以带空格
if (!reg.test(path)) {//校验不通过alert("请上传excel格式的文件!");return;
}

16.正则表达式 数字和字母组合且必须含有一个

$pattern = '/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,10}$/';
分开来注释一下:
^ 匹配一行的开头位置
(?![0-9]+$) 预测该位置后面不全是数字
(?![a-zA-Z]+$) 预测该位置后面不全是字母
[0-9A-Za-z] {6,10} 由6-10位数字或这字母组成
$ 匹配行结尾位置

17.低版本ie支持function.bind()

只需要添加一下代码,在需要的地方调用checkBind();就可以了

function checkBind()
{if (!Function.prototype.bind) {Function.prototype.bind = function(oThis) {if (typeof this !== "function") {throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");}var aArgs = Array.prototype.slice.call(arguments, 1),fToBind = this,fNOP = function() {},fBound = function() {return fToBind.apply(this instanceof fNOP && oThis ? this : oThis,aArgs.concat(Array.prototype.slice.call(arguments)));};fNOP.prototype = this.prototype;fBound.prototype = new fNOP();return fBound;};}
}

18.标题栏闪动提示


样式:

 JS代码:

var titleInit = document.title, isShine = true;setInterval(function() {var title = document.title;if (isShine == true) {if (/新/.test(title) == false) {document.title = '【你有新消息】';    } else {document.title = '【     】';}} else {document.title = titleInit;}
}, 500);window.onfocus = function() {isShine = false;
};
window.onblur = function() {isShine = true;
};// for IE
document.onfocusin = function() {isShine = false;
};
document.onfocusout = function() {isShine = true;
};


 

19.img图片垂直居中


#box{width:500px;height:400px;text-align:center;border:1px solid #d3d3d3;background:#fff;display: table-cell;vertical-align:middle;}#box img{vertical-align:middle;
}

20.decodeURI() 函数解码处理不了"+"

使用javascriptdecodeURIComponent函数解码查询字符串时,处理不了"+",例如下面

这里需要再做一下处理:

decodeURIComponent(str.replace(/\+/g, '%20'));

即在调用decodeURIComponent函数之前要先把+替换为%20,这样就没有问题了 

21.数组去重

方法1: (ES5)

function unique(a) {var res = [];for (var i = 0, len = a.length; i < len; i++) {var item = a[i];(res.indexOf(item) === -1) && res.push(item);}return res;
}var a = [1, 1, '1', '2', 1];
var ans = unique(a);
console.log(ans); // => [1, "1", "2"]

function unique(a) {var res = a.filter(function(item, index, array) {return array.indexOf(item) === index;});return res;
}var a = [1, 1, '1', '2', 1];
var ans = unique(a);
console.log(ans); // => [1, "1", "2"]

方法2: (ES6)

Set 以及 Array.from 方法:

function unique(a) {return Array.from(new Set(a));
}var a = [{name: "hanzichi"}, {age: 30}, new String(1), new Number(1)];
var ans = unique(a);
console.log(ans); // => [Object, Object, String, Number]

22.数组不是原始数据类型

typeof {} === 'object'  // true
typeof 'a' === 'string' // true
typeof 1 === number     // true
// But....
typeof [] === 'object'  // true

如果你想知道你的变量是不是数组,你仍然可以用Array.isArray(myVar)

原始数据 (原始值、原始数据类型)不是一种 object 类型并且没有自己的方法的。在 JavaScript 中,有六种原始数据类型:string,number,boolean,null,undefined,symbol (new in ECMAScript 2015)


23.两个数组内的元素相加

var a = [1,2,3,4,3];
var b = [4,5,6,7];
var c = a.map(function(v, i){return v + (b[i] || 0);
});
console.log(c);第二种考虑兼容
var a=[1,2,3,4,5];
var b=[6,7,8,9];
var c=[];
for (var i=0;i

24.一个数组插入到另一个数组

通过Array.prototype.push.apply方法将一个数组插入到另外一个数组

var a = [1,2,3];
var b = [4,5,6];
Array.prototype.push.apply(a, b);
console.log(a); //  [1, 2, 3, 4, 5, 6]

25.数字排序

Javascript 的sort()函数在默认情况下使用字母数字(字符串Unicode码点)排序。

所以

[1,2,5,10].sort()//会输出 [1, 10, 2, 5]

要正确的排序一个数组, 你可以用

[1,2,5,10].sort((a, b) => a — b)//会输出 从小到大排序[1, 2, 5, 10]

从大到小排序即

[1,2,5,10].sort((a, b) => b-a)

26.replace替换字符串

let s = "bob"
const replaced = s.replace('b', 'l')
replaced === "lob"
s === "bob"

我觉得这是一件好事,因为我不喜欢函数改变它们的输入。 你还应该知道 replace 只会替换第一个匹配的字符串:

如果你想替换所有匹配的字符串,你可以使用带/g标志的正则表达式 :

"bob".replace(/b/g, 'l') === 'lol' // 替换所有匹配的字符串

27. 比较的时候要注意

// These are ok
'abc' === 'abc' // true
1 === 1         // true
// These are not
[1,2,3] === [1,2,3] // false
{a: 1} === {a: 1}   // false
{} === {}           // false

原因:[1,2,3]和[1,2,3]是两个独立的数组。它们只是恰好包含相同的值。它们具有不同的引用,无法用===相比较。


28. 闭包

const Greeters = []
for (var i = 0 ; i < 10 ; i++) {Greeters.push(function () { return console.log(i) })
}
Greeters[0]() // 10
Greeters[1]() // 10
Greeters[2]() // 10

你是不是认为它会输出 0, 1, 2… ? 你知道它为什么不是这样输出的吗? 你会怎样修改让它输出 0, 1, 2… ?

这里有两种可能的解决方法:

  • 用 let 替代 var. Boom. 解决了.
let和var的不同在于作用域。var的作用域是最近的函数块,let的作用域是最近的封闭块,封闭块可以小于函数块(如果不在任何块中,则let和var都是全局的)。(来源)
  • 替代方法: 用 bind:

Greeters.push(console.log.bind(null, i))

29.当点击 复制 按钮的时候, 将选中的文字复制到粘贴板上


function clickBtn(){// 获取 input 元素var input = document.querySelector('#copytest');//或 var input = document.getElementById('copytest');input.focus();input.select();// 执行复制命令document.execCommand('Copy')}

核心代码 document.execCommand() 方法, 该方法的大概用途是 对选中区域 进行一些操作


30.JS获取textarea中剩余字数

html部分:


剩余可输入600字

js部分:

function changeLength(obj,num){obj.on('keyup',function(){var txtval = obj.val().length;//console.log(txtval);var str = parseInt(600-txtval);//console.log(str);if(str > 0 ){num.html('剩余可输入'+str+'字');}else {num.html('剩余可输入0字');obj.val(obj.val().substring(0, 600));}//console.log($('#num_txt').html(str));});
}
$(function(){ //我这里有四个,所以调用4次changeLength($('#text_txt1'),$('#num_txt1'));changeLength($('#text_txt2'),$('#num_txt2'));changeLength($('#text_txt3'),$('#num_txt3'));changeLength($('#text_txt4'),$('#num_txt4'));
});

31.js中的点击事件

//html

var btn=document.getElementById('btn');
//js 第一种:
btn.onclick=function(){alert('hello world');
}//消除事件
btn.onclick=null;//就不会弹出框了
//js 第二种:
btn.addEventListener('click',function(){alert('hello world')
},false);
btn.addEventListener('click',function(){alert(this.id)
},false);
//js 第三种:
function demo(){alert('hello');
}
js触发按钮点击事件
模拟JS触发按钮点击功能
  usually function      

//备注:
//btnObj.click()是真正地用程序去点击按钮,触发了按钮的onclick()事件
//btnObj.onclick()只是简单地调用了btnObj的onclick所指向的方法,
//只是调用方法而已,并未触发事件

32.清除浮动clearfix一种写法(stylus)

.clearfixdisplay :inline-block&:afterdisplay :blockcontent:"."height:0line-height: 0clear :bothvisibility :hidden

33.星星评分计算

很多商品评价中都会涉及评分,再根据评分计算星星个数

现介绍一种方法:

每个都是单个星星,分为

三种.png图

 const LENGTH = 5;//星星个数const CLS_ON = 'on';//全部选中星星的classNmaeconst CLS_HALF = 'half';//半个选中的classNmaeconst CLS_OFF = 'off';//未选中的classNmaelet result = [];let score = Math.floor(this.score * 2) / 2; //计算评分,如4.7会计算成4.5分,4.3会计算成4分let hasDecimal = score % 1 !== 0; //计算是否存在半颗星let integer = Math.floor(score); //计算有几个完全选中的星星for (let i = 0; i < integer; i++) {result.push(CLS_ON);//数组中添加全部选中星星的classNmae};if (hasDecimal) {result.push(CLS_HALF);//数组中添加半颗星星的classNmae};while (result.length < LENGTH) {result.push(CLS_OFF);//数组中补充未点亮星星的classNmae};return result;//返回数组

34.关闭页面弹框提示

类似下图效果

window.onbeforeunload=function (){var warning = "请确认保存后再退出哦!";return warning;
}
//注:现在不能弹出自定义的信息,暂时不知道原因,
//后续会追踪这个问题(如果你知道可以留下评论)
//关闭页面时的一些清楚缓存,ajax退出登录等操作可以写在函数里 

35.封装jsonp

import originJSONP from 'jsonp'// 封装的 jsonp 函数
export default function jsonp(url, data, options) {url += (url.indexOf('?') < 0 ? '?' : '&') + param(data)return new Promise((resolve, reject) => {originJSONP(url, options, (err, data) => {if(!err) {resolve(data)} else {reject(err)}})})
}// url 拼接函数
function param(data) {let url = ''for(let k in data) {let value = data[k] !== undefined ? data[k] : ''url += `&${k}=${encodeURIComponent(value)}`}return url ? url.substring(1) : ''
}


 

36.firefox 加入toolTip提示信息后 页面抖动

在firefox中 默认页面不超过一页是没有滚动条的 加入页面中某些元素会临时改变页面高度 比如用了toolTip 之类的提示小工具 就会出现滚动条时有时无 导致页面抖动

解决方法: 添加css代码

body{overflow: -moz-scrollbars-vertical;
}

37.判断游览器内核,自动添加前缀实现css属性兼容

let elementStyle = document.createElement('div').style
// 主流浏览器内核let vendor = (() => {let transfromNames = {webkit: 'webkitTransform',Moz: 'MozTransform',ms: 'msTransform',O: 'OTransform',standard: 'transform'}for (let key in transfromNames) {if (elementStyle[transfromNames[key]] !== undefined) {return key}}return false
})()// 添加样式的浏览器前缀
export function prefixStyle(style) {if (vendor === false) {return false}if (vendor === 'standard') {return style}return vendor + style.charAt(0).toUpperCase() + style.substr(1)
}

38.添加className

// 为元素添加类名
export function addClass(el, className) {// 先判断一下元素是否含有需要添加的类名,有则直接 returnif (hasClass(el, className)) {return}// 把该元素含有的类名以空格分割let newClass = el.className.split(' ')// 把需要的类名 push 进来newClass.push(className)// 最后以空格拼接el.className = newClass.join(' ')
}// 判断是否有要查看的 className,有则返回true,否则返回 false
export function hasClass(el, className) {let reg = new RegExp('(^|\\s)' + className + '(\\s|$)')return reg.test(el.className)
}

39.获取或设置data- 属性

export function getData(el, name, val) {const prefix = 'data-'name = prefix + nameif (val) {return el.setAttribute(name, val)} else {console.log('el.getAttribute(name)', el.getAttribute(name))return el.getAttribute(name)}
}

40.基于jq的datatables(兼容ie8)基本配置

描述:采用基于jq的datatables(兼容ie8)
主要功能:基本配置,服务端分页,清楚缓存,刷新等 /************************表格刷新*****************************/$("#searchFormBtn").click(function () {tablebyGroup.ajax.reload();});function queryUserByGroup() {tablebyGroup = $('#workArr').DataTable({destroy: true,serverSide: true,  //启用服务器端分页searching: false,  //禁用原生搜索orderMulti: false,  //启用多列排序order: [],  //取消默认排序查询,否则复选框一列会出现小箭头renderer: "bootstrap",  //渲染样式:Bootstrap和jquery-uipagingType: "simple_numbers",  //分页样式:simple,simple_numbers,full,full_numbersiDisplayLength:100,ajax: function (data, callback, settings) {var selected = $('#selectWorkArr').val();var param = {depId: parseInt(selected),docId: JSON.parse($.cookie('userinfo')).docId};//ajax请求数据$.ajax({type: "post",url: serverIp + "rest/doctor/selectWorkGroup?" + Math.random() + "&" + maiyaBuildParam(param),cache: false,  //禁用缓存
//                        data: JSON.stringify(param),  //传入组装的参数
//                        contentType: "application/json; charset=utf-8",dataType: "json",success: function (result) {var returnData = {};returnData.draw = data.draw;//这里直接自行返回了draw计数器,应该由后台返回returnData.recordsTotal = result.data.length;//返回数据全部记录returnData.recordsFiltered = result.data.length;//后台不实现过滤功能,每次查询均视作全部结果returnData.data = result.data;//返回的数据列表//调用DataTables提供的callback方法,代表数据已封装完成并传回DataTables进行渲染//此时的数据需确保正确无误,异常判断应在执行此回调前自行处理完毕callback(returnData);},error: function(msg) {alert(msg.message || '查询失败')}});},bFilter: false,//去掉搜索框方法bLengthChange: false, //去掉每页显示多少条数据方法"ordering": false,//禁止排序"columns": [{"data": "pName"},{"data": "pSex"},{"data": "strBirthDate"},{"data": "pCardNum"},{"data": "pPhone"},{"data": "cName"},{"data": "pActivited"}],paging: false,"columnDefs": [{"render": function(data, type, row, meta) {//渲染 把数据源中的标题和url组成超链接return ''+data+'';},//指定是第1列"targets": 0},{"render": function(data, type, row, meta) {return data == 1 && '男' || '女';},//指定是第1列"targets": 1},{"render": function(data, type, row, meta) {return data == 1 && '已注册' || '未注册';},//指定是第1列"targets": 6}]});}

41.打乱数组中元素顺序(类似音乐随机播放)

function getRandomInt(min, max) {return Math.floor(Math.random() * (max - min + 1) + min)
}export function shuffle(arr) {let _arr = arr.slice()for (let i = 0; i < _arr.length; i++) {let j = getRandomInt(0, i)let t = _arr[i]_arr[i] = _arr[j]_arr[j] = t}return _arr
}

扩展:

1.取[10,100) 的随机整数方法

Math.floor(Math.random()*90+10);

2.取[10,100] 的随机整数方法

function randomBy(under, over){ switch(arguments.length){ case 1: return parseInt(Math.random()*under+1); case 2: return parseInt(Math.random()*(over-under+1) + under); default: return 0; } 
} randomBy(10, 100);
//随机返回一个范围的数字randomNumber(n1, n2) {//randomNumber(5,10)//返回5-10的随机整数,包括5,10if (arguments.length === 2) {return Math.round(n1 + Math.random() * (n2 - n1));}//randomNumber(10)//返回0-10的随机整数,包括0,10else if (arguments.length === 1) {return Math.round(Math.random() * n1)}//randomNumber()//返回0-255的随机整数,包括0,255else {return Math.round(Math.random() * 255)}} 

3.利用sort()

我们先产生个数组

var arr=[];
for(var i=0;i<10;i++){arr.push(i)
}
console.log(arr)    // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

我们以前的正常排序是这样的:

arr.sort(function(a,b){return b-a
});

接下来我们来打乱它:

arr.sort(()=>{return Math.random() - 0.5
})                 // [1, 0, 2, 3, 4, 6, 8, 5, 7, 9]

第二种打乱方法:

arr.sort((a,b)=>{return a > Math.random()*10;
})                // [1, 2, 0, 6, 4, 3, 8, 9, 7, 5]

解析:

先说正常的排序:
a,b表示数组中的任意两个元素,若return > 0 ,b前a后;若reutrn < 0 则a前b后;当a=b时,则存在浏览器兼容 ;
a-b输出从小到大排序,b-a输出从大到小排序。
然后再说我们打乱的方法:
创建数组不用说,接下来就是用js的sort方法 来实现,Math.random()实现一个随机0-1之间的小数 然后再减去0.5,这时就会根据return比较后得到的值排序,所以说就会生成不是正常从大到小或者从小到大的排序。

42.函数节流(throttle)和 函数去抖(debounce)

函数节流 和 函数去抖 都是为了项目优化而出现的,官方是没有具体定义的,他们的出现主要是为了解决一些短时间内连续执行的事件带来性能上的不佳和内存的消耗巨大等问题;像这类事件一般像 scroll keyup mousemove resize等等,短时间内不断的触发,在性能上消耗是非常大的,尤其是一些改变DOM结构的操作;

节流[throttle]与防抖[debounce]非常相似,都是让上述这类事件里定义的代码 从不断的执行 更改成为 规定的时间内执行多少次;

函数节流(throttle) 应用场景

函数节流(throttle),例如实现一个拖拽功能,需要一路监听 mousemove 事件,在回调中获取元素当前位置,然后重置 dom 的位置(样式改变)。如果我们不加以控制,每移动一定像素而触发的回调数量是会非常惊人的,回调中又伴随着 DOM 操作,继而引发浏览器的重排与重绘,性能差的浏览器可能就会直接假死,这样的用户体验是非常糟糕的。我们需要做的是降低触发回调的频率,比如让它 500ms 触发一次,或者 1000ms,这个阈值不能太大,太大了拖拽就会失真,也不能太小,太小了低版本浏览器可能就会假死,这样的解决方案就是函数节流。函数节流的核心是,让一个函数不要执行得太频繁,减少一些过快的调用来节流

函数节流有哪些应用场景?哪些时候我们需要间隔一定时间触发回调来控制函数调用频率?

  • DOM 元素的拖拽功能实现(mousemove)
  • 射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)
  • 计算鼠标移动的距离(mousemove)
  • Canvas 模拟画板功能(mousemove)
  • 搜索联想(keyup)
  • 监听滚动事件判断是否到页面底部自动加载更多:给 scroll 加了 debounce 后,只有用户停止滚动后,才会判断是否到了页面底部;如果是 throttle 的话,只要页面滚动就会间隔一段时间判断一次

节流通俗来解释就比如我们水龙头放水,阀门一打开,水哗哗的往下流,这个秉着勤俭节约的优良传统美德,我们要把水龙头关小点,最好是如我们心意按照一定规律在某个时间间隔内一滴一滴的往下滴,这,,,好吧这就是我们节流的概念;换成函数来说,使用setTimeout方法,给定两个时间,后面的时间减去前面的时间,到达我们给定的时间就去触发一次这个事件,这么说太笼统的,我们看下面的函数,这里我们以【scroll】为例;

/** 样式我就顺便写了 **/
------------------------/** 先给定DOM结构;**/

------------------------/**主要看js,为了简单我用JQ去写了**/

export function throttle(delay, action){let last = return function(){let curr = +new Date()if (curr - last > delay){action.apply(this, arguments)last = curr }}
}

函数去抖(debounce) 应用场景

写代码之前,我们先清楚一下防抖的概念,不知道大家有没有做过电脑端两边悬浮广告窗口的这么一个东西,当我们拖动滚动条的时候,两边的广告窗口会因为滚动条的拖动,而不断的尝试着去居于中间,然后你就会看到这两个窗口,不停的抖啊抖;

一般这种就叫抖动了,我们要做的就是防止这种抖动,称为防抖[debounce ];

那这里防抖思想就是当我们拖动完成之后,两边的窗口位置再重新去计算,这样,就会显得很平滑,看着很舒服了,最主要的操作DOM结构的次数就大大减少了;

优化了页面性能,降低了内存消耗,不然你像IE这种比较老点版本的浏览器,说不定就直接给你蹦了

用书面一点的说法就是,在某个事件没有结束之前,函数不会执行,当结束之后,我们给定延时时间,然他在给定的延时时间之后再去执行这个函数,这就是防抖函数;

来看代码:

//将上面案例的throttle函数替换为debounce函数;
function debounce(method,time){var timer = null ;return function(){var context = this;//在函数执行的时候先清除timer定时器;clearTimeout(timer);timer = setTimeout(function(){method.call(context);},time);}
}

思路就是在函数执行之前,我们先清除定时器,如果函数一直执行,就会不断的去清除定时器中的方法,知道我们操作结束之后,函数才会执行;

export function debounce(func, delay) {let timerreturn function(...args) {if (timer) {clearTimeout(timer)}timer = setTimeout(() => {func.apply(this, args)}, delay)}
}

用途

  • 当我们做keyup像后台请求检验的时候,可以使用防抖函数,不然我们每按一次键盘就请求一次,请求太频繁,这样当我们结束按键盘的时候再去请求,请求少很多了,性能自然不用说;
  • resize 窗口大小调整的时候,我们可以采用防抖技术也可以使用节流;
  • mousemove 鼠标移动事件我们既可以采用防抖也可以使用节流;
  • scroll 滚动条触发的事件,当然既可以采用防抖也可以采用节流;
  • 连续高频发的事件都可以采用这两种方式去解决,优化页面性能;

具体的采用哪一种更较为合适,主要还是看你的业务需求

区分

节流说白了就是每ms执行一次函数,防抖就是 最后一次触发后ms后执行一次回调函数。
节流就是拧紧水龙头,让水滴一滴一滴流,而去抖则是按压一个弹簧,不松手则弹簧不会触发

函数节流和去抖都是限制基于DOM事件执行的javascript数量的方法,都是为了提高JS性能,但是两者是有区别的。

推荐阅读
函数节流和去抖之间的区别

本小节引用
avaScript 函数节流...
JavaScript 高级系列...

43.img宽高一样,border-radius: 50%,为什么不是正圆

这个是网上一个网友提的问题,自己未曾遇到也为实验,先保存在这
源代码:

 

原因:
图片的比例不是1:1(图片纵横比不为1)

解决方法:(待验证)

border-radius:100%

44.如何优雅的实现金钱格式化:1234567890 --> 1,234,567,890

用正则魔法实现:

var test1 = '1234567890'
var format = test1.replace(/\B(?=(\d{3})+(?!\d))/g, ',')console.log(format) // 1,234,567,890

非正则的优雅实现:

 function formatCash(str) {return str.split('').reverse().reduce((prev, next, index) => {return ((index % 3) ? next : (next + ',')) + prev})
}
console.log(formatCash('1234567890')) // 1,234,567,890

45.如何最佳的让两个整数交换数值

常规办法:

var a=1,b=2;
a += b;
b = a - b;
a -= b;

缺点也很明显,整型数据溢出,对于32位字符最大表示数字是2147483647,如果是2147483645和2147483646交换就失败了。
黑科技办法:

a ^= b;
b ^= a;
a ^= b;

es6:

[b,a] = [a,b]

46.实现标准JSON的深拷贝

var a = {a: 1,b: { c: 1, d: 2 }
}
var b=JSON.parse(JSON.stringify(a))

不考虑IE的情况下,标准JSON格式的对象蛮实用,不过对于undefined和function的会忽略掉。

47.在str前添加一个➕号,+str会强制转Number

不用Number、parseInt和parseFloat和方法把"88"字符串转换成数字

var str="88";
console.log(+str)   // 88
//或者
console.log(str - 0)   // 88
//但是如果是混合类型的字符串,则会转为NaN
var b="1606e";
console.log(+b)     // NaN

48.数组去重

方法1:最短的代码实现es6

[...new Set([1, "1", 2, 1, 1, 3])]function uniqueArray(arr){return Array.from(new Set(arr));
}

方法2:使用filter + indexOf

如下代码所示:

removeRepeatArray(arr) {return arr.filter(function (item, index, self) {return self.indexOf(item) === index;});
}

方法3:使用splice

如下代码所示:

function uniqueArray(arr){for(var i = 0; i < arr.length - 1; i++){for(var j = i + 1; j < arr.length; j++){if(arr[j] === arr[i]){arr.splice(j--, 1);}}}return arr;
}

方法4:只用Array
如下代码所示:

function uniqueArray(arr){var retArray = [];for(var i = 0; i < arr.length; i++){if(retArray.indexOf(arr[i]) < 0){retArray.push(arr[i]);}}return retArray;
}

方法5:Object.keys(对象)

   let a = ['1', '2', '3', 1,NaN,NaN,undefined,undefined,null,null, 'a', 'b', 'b'];const unique = arr => {var obj = {}arr.forEach(value => {obj[value] = 0;//这步新添加一个属性,并赋值,如果不赋值的话,属性会添加不上去})return Object.keys(obj);//`Object.keys(对象)`返回这个对象可枚举属性组成的数组,这个数组就是去重后的数组}console.log(unique(a));//["1", "2", "3", "NaN", "undefined", "null", "a", "b"]

注意:
这个方法会将 number,NaN,undefined,null,变为字符串形式,因为对象的属性名就是一个字符串

49.用最短的代码实现一个长度为m(6)且值都n(8)的数组

Array(6).fill(8)

50.取出一个数组中的最大值和最小值

var numbers = [5, 458 , 120 , -215 , 228 , 400 , 122205, -85411]; var maxInNumbers = Math.max.apply(Math, numbers); // 或 Math.max(...arr)var minInNumbers = Math.min.apply(Math, numbers); // 或 Math.min(...arr)

51.将argruments对象转换成数组

var argArray = Array.prototype.slice.call(arguments);

或者ES6:

var argArray = Array.from(arguments)

52.短路表达式

条件判断

var a = b && 1
// 相当于
if (b) {a = 1
} else {a = b
}
var a = b || 1
// 相当于
if (b) {a = b
} else {a = 1
}

53.RGB to Hex

function toHEX(rgb){return ((1<<24) + (rgb.r<<16) + (rgb.g<<8) + rgb.b).toString(16).substr(1);
}

54.JSON.stringify()妙用

1 语法
JSON.stringify(value[, replacer[, space]])
一般用法:

var user = {name: 'andy', isDead: false, age: 11, addr: 'shanghai'};
JSON.stringify(user);
"{"name":"andy","isDead":false,"age":11,"addr":"shanghai"}"

2 扩展用法
2.1 replacer
replacer可以是函数或者是数组。

功能1: 改变属性值
将isDead属性的值翻译成0或1,0对应false,1对应true

var user = {name: 'andy', isDead: false, age: 11, addr: 'shanghai'};
JSON.stringify(user, function(key, value){if(key === 'isDead'){return value === true ? 1 : 0;}return value;
});
//"{"name":"andy","isDead":0,"age":11,"addr":"shanghai"}"

功能2:删除某个属性
将isDead属性删除,如果replacer的返回值是undefined,那么该属性会被删除。

var user = {name: 'andy', isDead: false, age: 11, addr: 'shanghai'};
JSON.stringify(user, function(key, value){if(key === 'isDead'){return undefined;}return value;
});
//"{"name":"andy","age":11,"addr":"shanghai"}"

功能3: 通过数组过滤某些属性
只需要name属性和addr属性,其他不要。

var user = {name: 'andy', isDead: false, age: 11, addr: 'shanghai'};
JSON.stringify(user, ['name', 'addr']);
//"{"name":"andy","addr":"shanghai"}"

2.2 space
space可以是数字或者是字符串, 如果是数字则表示属性名前加上空格符号的数量,如果是字符串,则直接在属性名前加上该字符串。

功能1: 给输出属性前加上n个空格

var user = {name: 'andy', isDead: false, age: 11, addr: 'shanghai'};
JSON.stringify(user, null, 4);
"{"name": "andy","isDead": false,"age": 11,"addr": "shanghai"
}"

功能2: tab格式化输出

var user = {name: 'andy', isDead: false, age: 11, addr: 'shanghai'};
JSON.stringify(user, null, '\t');
"{"name": "andy","isDead": false,"age": 11,"addr": "shanghai"
}"

功能3: 搞笑

JSON.stringify(user, null, 'good');
"{
good"name": "andy",
good"isDead": false,
good"age": 11,
good"addr": "shanghai"
}"

2.3 深拷贝

var user = {name: 'andy', isDead: false, age: 11, addr: 'shanghai'};
var temp = JSON.stringify(user);
var user2 = JSON.parse(temp);

3 其他
JSON.parse() 其实也是支持第二个参数的。功能类似于JSON.stringify的第二个参数的功能。


55.获取jquery版本号

console.log('$',$.fn.jquery)
//$ 3.2.1

56.img异步加载图片

在开发中,我们经常有异步加载图片的请求,然后在图片加载成功后做一些操作,一般我们通过onload方法来实现.网上有两种写法,大家可以先看一下(注:logo.jpg是张本地图片):

例子1:

 var img = new Image();img.src = "logo.jpg";img.onload = function () {alert("image is loaded");};document.body.appendChild(img);

例子2:

 var img = new Image();img.onload = function () {alert("image is loaded");};img.src = "logo.jpg";document.body.appendChild(img);

发现什么了没有?上面两个例子最大的差别就在于onload和src赋值的先后顺序.那么onload和src赋值的先后顺序会在实际中产生什么差别呢?

产生这个问题的原因很简单,就是因为logo.jpg是本地图片,导致浏览器加载起来非常快,几乎在给img赋值src的时候,图片就已经加载完成,同时触发了onload事件,代码中为onload赋值的语句就相当于在onload事件发生后,这时候已经晚了.

将src写到了onload的前面,会导致onload来不及赋值就被执行了,所以正确的写法应该是第2个例子.既在给图片分配地址前,先绑定好它的onload事件,这样就不用担心错过时机的问题了.

正确的例子:

var img = new Image();
// 如果文档装入完成后加载用window load
//window.addEventListener("load" , function(){
//    document.body.appendChild(img);
//} , false);// 如果图片加载完毕用 img load
img.addEventListener('load', function(){document.body.appendChild(img);
} , false);img.src = 'test.png';

57.几个常用的console用法

1.console.log(): 进行标准输出流的输出(stdout)

console.group('mounted 挂载结束状态===============》');
console.log("%c%s", "color:green","data   : " + this.$data)

2.console.error(): 进行标准错误流的输出用法与console.log()一样.

3.console.dir(): 查看一个对象的内容,并把对象信息输出到控制台.

// a.js
var person = {age: 38,name: 'kobe',job: function(){return 'player'}
};
console.log(person);
// node a.js
{ age: 38, name: 'kobe', job: [Function: job] }

4.console.time()与console.timeEnd() : 可以用来统计一段代码的执行时间

// a.js
console.time('loop');
for(var i =0;i < 10000;i++){;
}
console.timeEnd('loop');
// node a.js
loop: 0.283ms

好玩的console.log()

console.log("%c3"," text-shadow: 0 1px 0 #ccc,0 2px 0 #c9c9c9,0 3px 0 #bbb,0 4px 0 #b9b9b9,0 5px 0 #aaa,0 6px 1px rgba(0,0,0,.1),0 0 5px rgba(0,0,0,.1),0 1px 3px rgba(0,0,0,.3),0 3px 5px rgba(0,0,0,.2),0 5px 10px rgba(0,0,0,.25),0 10px 10px rgba(0,0,0,.2),0 20px 20px rgba(0,0,0,.15);font-size:6em;line-height:60px;")console.log("%c2"," text-shadow: 0 1px 0 #ccc,0 2px 0 #c9c9c9,0 3px 0 #bbb,0 4px 0 #b9b9b9,0 5px 0 #aaa,0 6px 1px rgba(0,0,0,.1),0 0 5px rgba(0,0,0,.1),0 1px 3px rgba(0,0,0,.3),0 3px 5px rgba(0,0,0,.2),0 5px 10px rgba(0,0,0,.25),0 10px 10px rgba(0,0,0,.2),0 20px 20px rgba(0,0,0,.15);font-size:4em;line-height:60px;")console.log("%c1"," text-shadow: 0 1px 0 #ccc,0 2px 0 #c9c9c9,0 3px 0 #bbb,0 4px 0 #b9b9b9,0 5px 0 #aaa,0 6px 1px rgba(0,0,0,.1),0 0 5px rgba(0,0,0,.1),0 1px 3px rgba(0,0,0,.3),0 3px 5px rgba(0,0,0,.2),0 5px 10px rgba(0,0,0,.25),0 10px 10px rgba(0,0,0,.2),0 20px 20px rgba(0,0,0,.15);font-size:2em;line-height:60px;")console.log('%c南京热还是东京热.', 'color: #fff; background: #f40; font-size: 24px;border-radius:0 15px 15px 0;padding:10px;');console.log("%c                                           ","background-image:-webkit-gradient( linear, left top, right top, color-stop(0, #f22), color-stop(0.15, #f2f), color-stop(0.3, #22f), color-stop(0.45, #2ff), color-stop(0.6, #2f2),color-stop(0.75, #2f2), color-stop(0.9, #ff2), color-stop(1, #f22) );color:transparent;-webkit-background-clip: text;font-size:5em;width:1px;height:40px;padding:2px;")console.log("%c  热 热 热", "color:red;font-size:30px;font-weight:bolder;padding:50px 420px;line-height:10px;background:url('http://img.zcool.cn/community/0127c0577e00620000012e7e12da0e.gif') repeat-x;background-size:contain;");

58. !!强制转布尔值boolean

根据当前需要判断的值是真值还是假值来判断,真值返回true,假肢返回false,那么这样的话,除了假值,剩下的也都是真值了。

假值有:0 、 “” 、 null 、 undefined 、 false 、NaN

除了这 6 个外,其它均为“真” ,包括对象、数组、正则、函数等。
注意: '0'、'null'、'false'、{}、[]也都是真值 。
那么下面我们来看看!!是如何转布尔值的。
例如:
首先我们声明3个变量,x为null,y为空字符串,str为字符串,下面看看他们添加了"!!"后会有什么结果。
var x=null;
var y="";
var str="abcd";console.log(!!x)      // false;
console.log(!!y)      // false;
console.log(!!str)    // true;
如上所说,假值返回false,真值返回true。

59. 不可靠的undefined 可靠的void 0

在JavaScript中,假设我们想判断一个是否是 undefined,那么我们通常会这样写:

if(a === undefined){dosomething.....
}

因为在javascript中,undefined是不可靠的
例如:
当undefined被放在在function函数内,我们把它当成一个局部变量,它是可以赋上值的,下面我们来试试。

function foo2(){var undefined=1;console.log(undefined)
}
foo2();     // 1;

但是当在函数内定义一个全局变量,并不能给赋上值

var undefined;
function foo2(){undefined=1;console.log(undefined)
}
foo2()    // undefined

那么我们试试用void 0或者 void (0)来代替:
先声明一个变量a,赋值为undefined,接下来我们用void 0来判断一下。

var a=undefined;//用void 0来判断一下
if(a===void 0){console.log('true')
}       // true//再用void (0)来判断一下
if(a===void (0)){console.log('true')
}       // true
//最后我们打印一下这两个的返回值
console.log(void 0,void (0))    // undefined undefined

我们现在可以通过void 0 运算来获得 undefined;那在以后需要判断值为undefined的时候,可以直接用void 0或者void (0),而且这两个值的直接返回值就是undefined,所以说非常可靠哦!

60.用typeof来判断对象的潜在陷阱

问:使用 typeof bar === "object" 来确定 bar 是否是对象的潜在陷阱是什么?如何避免这个陷阱?

尽管 typeof bar === "object" 是检查 bar 是否对象的可靠方法,令人惊讶的是在JavaScript中 null 也被认为是对象!

因此,令大多数开发人员惊讶的是,下面的代码将输出 true 控制台:

var bar = null;
console.log(typeof bar === "object");  
// logs true!

只要清楚这一点,同时检查 bar 是否为 null,就可以很容易地避免问题:

console.log((bar !== null) && (typeof bar === "object")
);  
// logs false

要答全问题,还有其他两件事情值得注意:

首先,上述解决方案将返回 false,当 bar 是一个函数的时候。在大多数情况下,这是期望行为,但当你也想对函数返回 true 的话,你可以修改上面的解决方案为:

console.log((bar !== null) && ((typeof bar === "object") || (typeof bar === "function"))
);

第二,上述解决方案将返回 true,当 bar 是一个数组(例如,当 var bar = [];)的时候。

在大多数情况下,这是期望行为,因为数组是真正的对象,但当你也想对数组返回 false 时,你可以修改上面的解决方案为:

console.log((bar !== null)&& (typeof bar === "object") && (toString.call(bar) !== "[object Array]")
);

或者,如果你使用jQuery的话:

console.log((bar !== null)&& (typeof bar === "object") && (! $.isArray(bar))
);

或者 数组和函数返回false,但对于对象则为true:

console.log((bar !== null) && (bar.constructor === Object));

参考:
1.这些JavaScript编程黑科技...
2.图片的异步加载与onload函数
3.原生js的常用方法整理
4.ec-do-2.0.0.js


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部