js / jQuery使用过程中常见问题

目录

一、jQuery选择器选择选中的或者disabled的选择框时attr函数无效
二、jQuery each函数的break/continue
三、jQuery 获取元素的left会值/left数值
四、js 监听元素触摸/划屏动作
五、没设置导致$(window).height()不准确问题
六、jQuery获取/设置/监听下拉选择select的值
七、jQuery获取/设置/监听输入框input的值
八、js拼接html字符串时要注意先把单引号及双引号转义,不然可能会出现页面错误
九、绑定在scroll里面的方法在手机里面经常会等滚动完后再执行,有一定的延时,如何能缩短响应速度?
十、许多li间的drag and drop拖放的实
十一、顺序执行时,用js控制删除transition css3效果后再新加transition,旧的transition还生效
十二、返回顶部
十三、完美支持所有端的[复制到剪贴板]js插件-clipboard.js
十四、H5通过WebViewJavascriptBridge与APP进行交互时,H5获取APP的数据的异步时间不确定的问题。
十五、返回底部
十六、获取当前网站根域
十七、Url编码转义
十八、JSON与字符串互转
十九、jQuery样式选择器及样式名中最好不要出现大写字母,否则可能在webview里面执行不成功
二十、使用fastclick.js时如果用label包住checkbox或者radio按钮里面同时出现其他如span或者i元素时,在ios里会出现点击不了的情况
二十一、slice与splice的使用
二十二、删除页面上所有的img和iframe
二十三、js能过userAgent判断各种设备终端
二十四、document.body.scrollTop 一直都是 0 的问题
二十五、原生js获取元素宽高
二十六、jQuery获取元素位置、宽高
二十七、js动态加载脚本
二十八、javascript 操作符(~、&、|、^、<<、>>)(操作数是32整数范围内)
二十九、audio标签声音文件如何重播?replay?
三十、js中如何使用FormData或者Ajax方式上传文件
三十一、js中的call、apply、bind的使用方法
三十二、加载js用async和defer的区别
三十三、非cookie情况下,前端实现访问终端的唯一标识:Fingerprintjs2
三十四、Debounce和Throttle的区别
三十五、原生js做上拉到底部加载
三十六、js正则过滤emoji表情输入
三十七、WPS2013造成的HTML5 file.type值异常
三十八、js如何判断网络是否正常
三十九、在QQ/微信浏览器里面使用el.scrollTo(0, 0)无效的问题
四十、js如何实现input=file对要上传的图片进行预览
四十一、如何创建一个干净的对象
四十二、0 == ” // => true、’2′ > ’11’的坑
四十三、ios8的坑。Dom类数组,要先转为数组才可以使用forEach进行遍历
四十四、为什么要用sessionStorage?
四十五、js操作视频相关用法
四十六、ios/ie11中new Date(‘2017-08-11 12:00:00’)设置日期不成功问题
四十七、canvas图片绘制后转图片url跨域问题Tainted canvases may not be exported
四十八、创建一个a链接 使用a.click()模拟点击,主流浏览器可以,但是在ie10以下不能生效
四十九、使用 void 返回纯正的undefined
五十、FormData 使用方法详解
五十一、返回、前进、刷新页面方法
五十二、js 边界,分母为 0 问题
五十三、eval 中使用正则表达式对 \ 处理异常
五十四、window.open 深度使用方法
五十五、原生 Dom 节点类似 el.style.width=100 写法无效,建议全部用字符串如 el.style.width=”100px”


一、jQuery选择器选择选中的或者disabled的选择框时attr函数无效

jQuery代码如下:

if (!$obj.prop("disabled")){//用prop选择或者设置对象值
     $obj.prop("checked", This.prop("checked"));
}

或者

$obj.is(":checked");

二、jQuery each函数中如何实现break/continue

jQuery代码如下:

return false;//break
return true;//continue

 

三、jQuery 获取元素的left会值/left数值

$obj.position().left;//获取数值
$obj.css("left");//获取值-如1px

 

四、js 监听元素触摸/划屏动作

                var el=document.getElementById("example"),
                    startPos = { x: 0, y: 0 },
                    currentPos = { x: 0, y: 0 };
                el.addEventListener('touchstart', function (event) {
                    startPos = { x: event.changedTouches[0].pageX, y: event.changedTouches[0].pageY };
                }, false);
                el.addEventListener('touchmove', function (event) {
                    event.preventDefault();//阻止默认的触屏滚动动作
                    currentPos = { x: event.changedTouches[0].pageX, y: event.changedTouches[0].pageY };
                }, false);
                el.addEventListener('touchend', function (event) {
                    currentPos = { x: event.changedTouches[0].pageX, y: event.changedTouches[0].pageY };
                    if (currentPos.x != startPos.x){
                        //你左右划动
                    }
                    if (currentPos.y != startPos.y){
                         //你上下划动
                    }
                    startPos = { x: 0, y: 0 },
                    currentPos = { x: 0, y: 0 };
                }, false);

 

五、没设置导致$(window).height()不准确问题

只要在页面顶部加上就可以

<!DOCTYPE html>

 

六、jQuery获取/设置下拉选择select的值

$(obj).val();//获取
$(obj).val(val);//设置
$(obj).change(function(){
    //监听选择修改
});

 

七、jQuery获取/设置/监听输入框input的值

$(obj).on("input propertychange",function(){//监听
    var val=$(this).val(),//获取
        $(obj2).val(val);//设置 
});

 

八、js拼接html字符串时要注意先把单引号及双引号转义,不然可能会出现页面错误

htmlStr = htmlStr .replace("'","&apos;").replace('"','&quot;');//"是双引号转义,'是单引号转义

 

九、绑定在scroll里面的方法在手机里面经常会等滚动完后再执行,有一定的延时,如何能缩短响应速度?

/**
 * 简易的事件添加方法
 * http://www.zhangxinxu.com/wordpress/2013/04/js-mousewheel-dommousescroll-event/
 * 
 * @param {Element} el
 * @param {String} type
 * @param {Function} fn
 * @param {Boolean} capture
 */
window.addEvent = (function (window, undefined) {
    var _eventCompat = function (event) {
        var type = event.type;
        if (type == 'DOMMouseScroll' || type == 'mousewheel') {
            event.delta = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
        }
        if (event.srcElement && !event.target) {
            event.target = event.srcElement;
        }
        if (!event.preventDefault && event.returnValue !== undefined) {
            event.preventDefault = function () {
                event.returnValue = false;
            };
        }
        /* 
           ......其他一些兼容性处理 */
        return event;
    };
    if (window.addEventListener) {
        return function (el, type, fn, capture) {
            if (type === "mousewheel" && document.mozHidden !== undefined) {
                type = "DOMMouseScroll";
            }
            el.addEventListener(type, function (event) {
                fn.call(this, _eventCompat(event));
            }, capture || false);
        }
    } else if (window.attachEvent) {
        return function (el, type, fn, capture) {
            el.attachEvent("on" + type, function (event) {
                event = event || window.event;
                fn.call(el, _eventCompat(event));
            });
        }
    }
    return function () { };
})(window);
// 主要是用touch代替scroll来监听
addEvent(document.body, 'touchstart', function (event) {
    startY = event.changedTouches[0].pageY;
}, false);
addEvent(document.body, 'touchmove', function (event) {
    currentY = event.changedTouches[0].pageY;
    Y = currentY - startY;
    if (Y > 10) {
        // 向上滚动执行
    } else if (Y < -10) {
        // 向下滚动执行
    }
}, false);

 当然直接用addEventListener代替addEvent也可以。

十、许多li间的drag and drop拖放的实现

html代码如下:

           <ul>

                <li draggable="true" ondrop="drop(event)" ondragover="allowDrop(event)" ondragstart="drag(event)">
                    <div class="goods-thumb"><img title="480" src="http://dummyimage.com/480/FF8604/fff"></div>
                </li>
                <li draggable="true" ondrop="drop(event)" ondragover="allowDrop(event)" ondragstart="drag(event)">
                    <div class="goods-thumb"><img title="480" src="http://dummyimage.com/480/FF8704/fff"></div>
                </li>
                <li draggable="true" ondrop="drop(event)" ondragover="allowDrop(event)" ondragstart="drag(event)">
                    <div class="goods-thumb"><img title="480" src="http://dummyimage.com/480/FF8702/fff"></div>
                </li>
                <li draggable="true" ondrop="drop(event)" ondragover="allowDrop(event)" ondragstart="drag(event)">
                    <div class="goods-thumb"><img title="480" src="http://dummyimage.com/480/FC8604/fff"></div>
                </li>
                <li draggable="true" ondrop="drop(event)" ondragover="allowDrop(event)" ondragstart="drag(event)">
                    <div class="goods-thumb"><img title="480" src="http://dummyimage.com/480/FE8704/fff"></div>
                </li>
                <li draggable="true" ondrop="drop(event)" ondragover="allowDrop(event)" ondragstart="drag(event)">
                    <div class="goods-thumb"><img title="480" src="http://dummyimage.com/480/FA8702/fff"></div>
                </li>
            </ul>

JS代码如下:

  // 拖放效果 内加防止img或div被拖效果
  var liEl = undefined;
  function drag(ev) {
    ev.stopPropagation();
    liEl = ev.target;
    if (ev.target.tagName != 'LI'){
      liEl = $(ev.target).parents('li').get(0);
    }  
  }

  function drop(ev) {
    var tempEl = ev.target;
    if (ev.target.tagName != 'LI'){
      tempEl = $(ev.target).parents('li').get(0);
    }     
    $(tempEl).before(liEl);
    liEl = undefined;
    ev.preventDefault();
  }
  function allowDrop(ev) {
    ev.preventDefault();
  } 

 

十一、顺序执行时,用js控制删除transition css3效果后再新加transition,旧的transition还生效

解决方式:加上个setTimeout去新增新的transition就可以生效
 

十二、返回顶部

window.scrollTo(0,0); // 纯js
$('html,body').animate({scrollTop: '0px'}, 800); // jQuery

 

十三、完美支持所有端的[复制到剪贴板]js插件-clipboard.js

    <script src="//cdn.bootcss.com/clipboard.js/1.6.1/clipboard.min.js"></script>
    <script>
        var clipboard = new Clipboard('#copy');

        clipboard.on('success', function (e) {
            e.clearSelection();
            alert('复制成功!');
        });

        clipboard.on('error', function (e) {
            alert('复制失败,手机不支持哦,请长按ID进行复制吧');
        });
    </script>

 

十四、H5通过WebViewJavascriptBridge与APP进行交互时,H5获取APP的数据的异步时间不确定的问题。

 js代码如下(这段代码一般是放在head头部来执行):

		var reqDataUid;
		var reqDataToken;
		var sendToApp;
		//判断是否为Android
		function _IsAndroid() {
		    var ua = navigator.userAgent.toLowerCase();
		    if (ua.match(/Android/i) == "android") {
		        return true;
		    } else {
		        return false;
		    }
		}
		//接口样式
		function setupWebViewJavascriptBridge(callback) {
	        if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
	        if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
	        window.WVJBCallbacks = [callback];
	        var WVJBIframe = document.createElement('iframe');
	        WVJBIframe.style.display = 'none';
	        if(_IsAndroid()){
	        	WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__';
	        }else{
	        	WVJBIframe.src = 'https://__bridge_loaded__';
	        }
	        //WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__';//'https://__bridge_loaded__';
	        document.documentElement.appendChild(WVJBIframe);
	        setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
	    }
		setupWebViewJavascriptBridge(function(bridge) {
			bridge.registerHandler('RequestUserData', function(data, responseCallback) {// APP端定义好的供js调用的用户数据请求接口
		        reqDataUid = (_IsAndroid() ? JSON.parse(data).uid : data.uid);
		        reqDataToken = (_IsAndroid() ? JSON.parse(data).token : data.token);
// 这里可以使用获得的数据,setupWebViewJavascriptBridge这函数其实是异步执行的,因此执行时间不确定,可以有技巧的来使用,如果要输出dom节点可以自定义一个domready的函数,然后ready以后通过拼接html的方式输出到相应的dom节点

		        responseCallback('XXXX'); // 回调
			});
			// H5主动给APP发送信息
			sendToApp = function (type,val){
				bridge.callHandler('SendDataToApp', {'type': type,'value':val}, function(response) {
					//log('JS got response', response);
				})
			}
		});

解决方案:

方案1、可以让APP端在webview打开之前先把信息写到cookie里面先;

方案2、可以类似微信的wx.ready一样,在wx对象里面封装好一个wx.ready(function(wx){})的callback函数来执行,这里我们可以定义一个appReady的函数
 

// 针对上面的情况可以用监听的方式来实现
        var appReady = function(callback){
                var _getIdTimer = setInterval(function(){
                if(reqDataUid != undefined && reqDataToken != undefined){
                    callback();
                    clearInterval(_getIdTimer);
                }
            },10);
        };

 

十五、返回底部

            var h = $(document).height()-$(window).height();
            $(document).scrollTop(h); 

或者

                        var h = document.documentElement.scrollHeight || document.body.scrollHeight;
                        window.scrollTo(h, h);

十六、获取当前网站根域

 if (!window.location.origin) {
        window.location.origin = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '');
 }

 

十七、Url编码转义

encodeURIComponent(URIstring); // 常用作URL编码其中的某些字符(比如 :;/?:@&=+$,# 这些用于分隔 URI 组件的标点符号)将被十六进制的转义序列进行替换

encodeURI(URIstring); // 该方法的目的是对 URI 进行完整的编码,因此对以下在 URI 中具有特殊含义的 ASCII 标点符号,encodeURI() 函数是不会进行转义的:;/?:@&=+$,#

escape(string); // 不会对 ASCII 字母和数字进行编码,也不会对下面这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。其他所有的字符都会被转义序列替换。

十八、JSON与字符串互转

JSON.parse(string); // STRING -> JSON, string没有用引号引起来,使用JSON.parse所有浏览器中均抛异常

JSON.stringify(value [, replacer] [, space]); // JSON -> STRING, replacer可选,用于过滤不必要的key,可以是数组也可以是函数

 

十九、jQuery样式选择器及样式名中最好不要出现大写字母,否则可能在webview里面执行不成功

 $('#obj').on('click','.myElement',function(e){ // 类似样式名出现大写字母的写法可能在APP的webview里面不执行
     // ...
});

 

二十、使用fastclick.js时如果用label包住checkbox或者radio按钮里面同时出现其他如span或者i元素时,在ios里会出现点击不了的情况

解决方案:

给label里面的span或者i元素添加样式 pointer-events: none; 就可以了

二十一、slice与splice的使用

slice方法:从已有的数组中返回选定的元素

Array.slice(start,end)
// start    必需。规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。也就是说,-1 指最后一个元素,-2 指倒数第二个元素,以此类推。
// end    可选。规定从何处结束选取。该参数是数组片断结束处的数组下标。如果没有指定该参数,那么切分的数组包含从 start 到数组结束的所有元素。如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素。

 
splice方法:向/从数组中添加/删除项目,然后返回被删除的项目。该方法会改变原始数组

Array.splice(index,howmany,item1,.....,itemX) 
// index    必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。
// howmany    必需。要删除的项目数量。如果设置为 0,则不会删除项目。
// item1, ..., itemX    可选。向数组添加的新项目。

 

二十二、删除页面上所有的img和iframe

    var imgs = document.querySelectorAll('img');
    var iframes = document.querySelectorAll('iframe');
    imgs.forEach(function (img) {
        var oldNode = img;
        oldNode.parentNode.removeChild(oldNode);
    });
    iframes.forEach(function (img) {
        var oldNode = img;
        oldNode.parentNode.removeChild(oldNode);
    });

 

二十三、js能过userAgent判断各种设备终端

        var isMobile = {
            UCBrowser: function () {
                return navigator.userAgent.match(/UCBrowser/i);
            },
            QQ: function () {
                return navigator.userAgent.match(/QQ\//i);
            },          
            MicroMessenger: function () {
                return navigator.userAgent.match(/MicroMessenger/i);
            },
            Android: function () {
                return navigator.userAgent.match(/Android/i);
            },
            BlackBerry: function () {
                return navigator.userAgent.match(/BlackBerry/i);
            },
            iPad: function () {
                return navigator.userAgent.match(/iPad/i);
            },
            iPhone: function () {
                return navigator.userAgent.match(/iPhone/i);
            },
            iOS: function () {
                return navigator.userAgent.match(/iPhone|iPod|iPad/i);
            },
            Opera: function () {
                return navigator.userAgent.match(/Opera Mini/i);
            },
            Windows: function () {
                return navigator.userAgent.match(/IEMobile/i);
            },
            any: function () {
                return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows())
            }
        };

 

二十四、document.body.scrollTop 一直都是 0 的问题

页面具有 DTD(或者说指定了 DOCTYPE)时,使用 document.documentElement,兼容写法如下:
 

var currentScrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;

 

二十五、原生js获取元素宽高及对应位置

标签元素的宽高值获取
//绝对宽度
Obj.offsetWidth
//绝对高度
Obj.offsetHeight/*以下是获取窗口对象的宽高值。
clientHeight   获取对象的高度,不计算任何边距、边框、滚动条,但包括该对象的补白。
clientLeft   获取   offsetLeft   属性和客户区域的实际左边之间的距离。
clientTop   获取   offsetTop   属性和客户区域的实际顶端之间的距离。
clientWidth   获取对象的宽度,不计算任何边距、边框、滚动条,但包括该对象的补白。
clientX   设置或获取鼠标指针位置相对于窗口客户区域的   x   坐标,其中客户区域不包括窗口自身的控件和滚动条。 
clientY   设置或获取鼠标指针位置相对于窗口客户区域的   y   坐标,其中客户区域不包括窗口自身的控件和滚动条。
clip   设置或获取定位对象的哪个部分可见。
clipBottom   获取对象剪裁区域的底边坐标。
clipLeft   获取对象剪裁区域的左边坐标。
clipRight   获取对象剪裁区域的右边坐标。
clipTop   获取对象剪裁区域的顶边坐标。*/

二十六、jQuery获取元素位置、宽高

$(window).height(); //是文档窗口高度 
$("div").offset().top; //是标签距离顶部高度
$("div").offset().left; //是标签距离右边高度
$(document).scrollTop(); //是滚动条高度
$("div").height(); //是标签高 
$("div").width(); //是标签宽 
$("div").outerHeight(); //是标签总高 
$("div").outerWidth(); //是标签总宽 
$("div").offset().top-$(document).scrollTop(); //元素相对屏幕高度位置

二十七、js动态加载脚本

    function loadScript(url, callback) {
        var script = document.createElement("script")
        script.type = "text/javascript";
        if (script.readyState) { //IE
            script.onreadystatechange = function () {
                if (script.readyState == "loaded" || script.readyState == "complete") {
                    script.onreadystatechange = null;
                    callback();
                }
            };
        } else { //Others
            script.onload = function () {
                callback();
            };
        }
        script.src = url;
        document.getElementsByTagName("head")[0].appendChild(script);
    }

二十八、javascript 操作符(~、&、|、^、<<、>>)(操作数是32整数范围内)

        //1、按位非~
        var num1=25;//
        var num2=~num1;// -26
        //说明:相信大家也已经看出来了按位~(NOT)的实现原理:
        //以num1、num2为讲解对象
        //第一步:先把num1转换成二进制
        //第二步:取得num1二进制的反码赋值给num2
        //第三步:在把num2换算成十进制数字
        //简单说明:就是把操作数的数值的负数减1
        //2、按位与 &(AND)
        var result=25 & 3;
        alert(result);//1
        //说明,就是把两数转换成二进制数字,按照一定的规则:
        //第一个数值的位       第二个数值的位     结果
        //  1                       1           1
        //  1                       0           0
        //  0                       1           0
        //  0                       0           0
        //简而言之,按位操作符的相对应的位都是1时则返回1,任何一位是0则返回0.
        //然后在得到的二进制转换成十进制数字
      //  25=0000 0000 0000 0000 0000 0000 0001 1001
      //  3= 0000 0000 0000 0000 0000 0000 0000 0011
      //  ------------------------------------------
      // AND=0000 0000 0000 0000 0000 0000 0000 0001
        //3、按位或 |(OR)
        var result=25 | 3;
        alert(result);//27
        //说明,就是把两数转换成二进制数字,按照一定的规则:
        //第一个数值的位       第二个数值的位     结果
        //  1                       1           1
        //  1                       0           1
        //  0                       1           1
        //  0                       0           0
        //简而言之,按位操作符的相对应的位有一位是1就返回1,而只有在两个位都是0的情况下才返回0.
        //然后在得到的二进制转换成十进制数字
        //  25=0000 0000 0000 0000 0000 0000 0001 1001
        //  3= 0000 0000 0000 0000 0000 0000 0000 0011
        //  ------------------------------------------
        //  OR=0000 0000 0000 0000 0000 0000 0001 1011
        //4、按位异或 ^(XOR)
        var result= 25 ^ 3;
        alert(result);//26
        //说明,就是把两数转换成二进制数字,按照一定的规则:
        //第一个数值的位       第二个数值的位     结果
        //  1                       1           0
        //  1                       0           1
        //  0                       1           1
        //  0                       0           0
        //简而言之,这个操作符(^)在两个数值对应位上只有一个1时才返回1,否则返回0.
        //然后在得到的二进制转换成十进制数字
        //  25=0000 0000 0000 0000 0000 0000 0001 1001
        //  3= 0000 0000 0000 0000 0000 0000 0000 0011
        //  ------------------------------------------
        // XOR=0000 0000 0000 0000 0000 0000 0001 1010
        //5、左移(<<)
        var oldNum=2;
        var newNum=oldNum << 5;
        alert(newNum)
        //说明,将2(二进制数码10)向左移5位结果就是1000000(二进制)等于64
        //注意,左移不会影响操作符的符号位,例如将-2左移5位就是-64
        //2=0000 0000 0000 0000 0000 0000 0000 0010
       //64=0000 0000 0000 0000 0000 0000 010 00000
        //6、有符号右移(>>)
        var oldNum=64;
        var newNum=oldNum >> 5;
       //64=0000 0000 0000 0000 0000 0000 010 00000
        //2=0000 0000 0000 0000 0000 0000 0000 0010
        alert(newNum)

二十九、audio标签声音文件如何重播?replay?

audioElement.currentTime=0;
audioElement.play();

三十、js中如何使用FormData或者Ajax方式上传文件

 可参考:FormData 对象的使用
Using XMLHttpRequest
Sending and Receiving Binary Data

三十一、js中的call、apply、bind的使用方法

 
在JavaScript中,call、apply和bind是Function对象自带的三个方法,这三个方法的主要作用是改变函数中的this指向。
bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。
如下代码:call 需要把参数按顺序传递进去,而 apply 则是把参数放数组里。

function class1(args1,args2){       
  this.name=function(){      
   console.log(args1,args2);      
  }     
}     
function class2(){    
  var args1="1";
  var args2="2";
  class1.call(this,args1,args2);  
  /**/
  class1.apply(this,[args1,args2]);
}
var c=new class2();   
c.name(); // => 1 2

在JavaScript 中,某个函数的参数数量是不固定的,因此要说适用条件的话,当你的参数是明确知道数量时用 call ;而不确定的时候用 apply,然后把参数 push 进数组传递进去。当参数数量不确定时,函数内部也可以通过 arguments 这个数组来遍历所有的参数。

MDN的解释是:bind()方法会创建一个新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以创建它时传入 bind()方法的第一个参数作为 this,传入 bind() 方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数

var bar=function(){   
  console.log(this.x);   
}
var foo={ 
     x:3   
} 
bar();  // => undefined
bar.bind(foo)(); // => 3
/**/ 
var func=bar.bind(foo);   
func(); // => 3

在react中也经常要用到把this绑回(bind)到自带函数中供调用。
 

三十二、加载js用async和defer的区别

都是异步加载,但执行时机不一样,async是加载后马上执行,defer是等到DOMContentLoaded后才执行,类似jQuery的$(document).ready(function(){});
 

三十三、非cookie情况下,前端实现访问终端的唯一标识:Fingerprintjs2

https://github.com/Valve/fingerprintjs2
 

三十四、Debounce和Throttle的区别

Debounce是把多个连续的事件组合成一个执行,而Throttle是约束事件执行的频率及可以设一个最小间隔

// Debounce把200毫秒内的事件组合
$(window).on('scroll', _.debounce(doSomething, 200));
// Throttle事件执行的间隔最少为200毫秒
$(window).on('scroll', _.throttle(doSomething, 200));

 

三十五、原生js做上拉到底部加载

    window.onscroll = debounce(function () {
      var dH = document.documentElement.scrollHeight || document.body.scrollHeight;
      var sT = document.documentElement.scrollTop || document.body.scrollTop;
      var wH = document.documentElement.clientHeight || document.body.clientHeight;

      if (wH + sT >= dH - 80) {
        loadmore();
      }
    }, 200);

 

三十六、js正则过滤emoji表情输入

      const emojiReg = /[^\u0020-\u007E\u00A0-\u00BE\u2E80-\uA4CF\uF900-\uFAFF\uFE30-\uFE4F\uFF00-\uFFEF\u0080-\u009F\u2000-\u201f\u2026\u2022\u20ac\r\n]/g
      str = str.replace(/\s+/g, '').replace(emojiReg, '') // 过滤空格及emoji

 

三十七、WPS2013造成的HTML5 file.type值异常

如果装了wps2013,在网页中使用file组件时,office文件的file.type会变为空值,可以通过file.name进行文件类型的判断

 

三十八、js如何判断网络是否正常

if (navigator && navigator.onLine === false) {
  alert("无法连接网络")
} else {
 alert("正常上网")
}

 

三十九、在QQ/微信浏览器里面使用el.scrollTo(0, 0)无效的问题

解决方法如下(但部分荣耀手机设置scrollLeft却无效……,可以兼容地来使用):

el.scrollLeft = 0 // 可使用scrollLeft或者scrollTop动态设置

 

四十、js如何实现input=file对要上传的图片进行预览

 

// 方式一 使用FileReader
        var reads= new FileReader();
        f=document.getElementById('file').files[0];
        reads.readAsDataURL(f);
        reads.onload=function (e) {
            document.getElementById('show').src=this.result;
        };

// 方式二 使用window.URL.createObjectURL
        var url = null ;
        // 下面函数执行的效果是一样的,只是需要针对不同的浏览器执行不同的 js 函数而已
        if (window.createObjectURL!=undefined) { // basic
            url = window.createObjectURL(file) ;
        } else if (window.URL!=undefined) { // mozilla(firefox)
            url = window.URL.createObjectURL(file) ;
        } else if (window.webkitURL!=undefined) { // webkit or chrome
            url = window.webkitURL.createObjectURL(file) ;
        }

// 参考引用: https://blog.csdn.net/weixin_38023551/article/details/78318532 

 

四十一、如何创建一个干净的对象

var emptyObj = Object.create(null) // => {}No properties,干净的,没有任务的属性
var obj = {} // => {}__proto__: Object 不干净的,继承了Object对象的所有属性

 

四十二、0 == ” // => true 和 ‘2’ > ’11’ 的坑

1、要如何解决0==”的坑?使用全===吧,0===” // => false;2、要解决字符串 ‘2’ > ’11’ 误比较问题,要记住比较前先把其中一个转为 Number 类型。
 

四十三、ios8的坑。Dom类数组,要先转为数组才可以使用forEach进行遍历

 

const els = [...document.querySelectorAll('.el')]

 

四十四、为什么要用sessionStorage?

sessionStorage 与 localStorage 的接口类似,但保存数据的生命周期与 localStorage 不同。做过后端开发的同学应该知道 Session 这个词的意思,直译过来是“会话”。而 sessionStorage 是一个前端的概念,它只是可以将一部分数据在当前会话中保存下来刷新页面数据依旧存在但当页面关闭后,sessionStorage 中的数据就会被清空
 

四十五、js操作视频相关用法

https://github.com/webrtc/samples

https://www.cnblogs.com/scarecrowlxb/p/6804747.html

https://www.cnblogs.com/scarecrowlxb/p/9573976.html
 
 

四十六、ios中new Date(‘2017-08-11 12:00:00’)设置日期不成功问题

new Date("2017-08-11 12:00:00".replace(/-/g, '/')) // 需写成这样

 

四十七、canvas图片绘制后转图片url跨域问题Tainted canvases may not be exported

 前后端一起改,前端请求图片时增加 img.crossOrigin = ‘anonymous’,后端要设置允许跨域请求

function preLoadCrossOriginImage (url, callback) { // fixed Chrome 图片load不出来问题
    let img = new Image() //创建一个Image对象,实现图片的预下载  
    img.crossOrigin = 'anonymous'
    img.src = url
  
    if (img.complete) { // 如果图片已经存在于浏览器缓存,直接调用回调函数  
      callback && callback.call(img)
      return // 直接返回,不用再处理onload事件  
    }
  
    img.onload = function () { //图片下载完毕时异步调用callback函数。  
      callback && callback.call(img) //将回调函数的this替换为Image对象  
    }
  }
response.setHeader("Access-Control-Allow-Origin", "https://www.xxxx.com") // 后端

 

四十八、创建一个a链接 使用a.click()模拟点击,主流浏览器可以,但是在ie10以下不能生效

ie10以下,createElement创建的是一个对象,需要把他添加到一个元素后面
 

        const a = document.createElement('a')
        a.href = 'http://www.xxx.com'
        document.body.appendChild(a)
        a.click() // 点击
        document.body.removeChild(a) // 点击完成移除元素

使用 void 返回纯正的undefined

不管void后的运算数是什么,都会返回纯正的undefined

void 1 === undefined // => true
void 0 === undefined // => true

五十、FormData 使用方法详解

FormData 表单提交方式:

默认情况下 Content-Type 是 application/x-www-form-urlencoded,如果要发送大量的二进制数据(non-ASCII),比如要上传文件,应该使用 multipart/form-data 格式

FormData 的主要用途有两个:

1、将 form 表单元素的 name 与 value 进行组合,实现表单数据的序列化,从而减少表单元素的拼接,提高工作效率。

2、异步上传文件

操作方法:

1、通过 get(key) 与 getAll(key) 来获取相对应的值

// 获取 key 为 age 的第一个值
formdata.get("age"); 
 // 获取 key 为 age 的所有值,返回值为数组类型
formdata.getAll("age");

2、通过 append(key,value) 在数据末尾追加数据

// 通过 FormData 构造函数创建一个空对象
var formdata = new FormData();
// 通过 append() 方法在末尾追加 key 为 name 值为 laoliu 的数据
formdata.append("name","laoliu");
// 通过 append() 方法在末尾追加 key 为 name 值为 laoli 的数据
formdata.append("name","laoli");
// 通过 append() 方法在末尾追加 key 为 name 值为 laotie 的数据
formdata.append("name","laotie");
// 通过 get 方法读取 key 为 name 的第一个值
console.log(formdata.get("name")); // laoliu
// 通过 getAll 方法读取 key 为 name 的所有值
console.log(formdata.getAll("name")); // ["laoliu", "laoli", "laotie"]

3、通过 set(key, value) 来设置修改数据

// 通过 FormData 构造函数创建一个空对象
var formdata = new FormData();
// 如果 key 的值不存在会为数据添加一个 key 为 name 值为 laoliu 的数据
formdata.set("name","laoli");
// 通过 get 方法读取 key 为 name 的第一个值
console.log(formdata.get("name")); // laoli

4、通过 has(key) 来判断是否存在对应的 key 值

//通过 FormData 构造函数创建一个空对象
var formdata = new FormData();
// 通过 append() 方法在末尾追加 key 为 name 值为 laoliu 的数据
formdata.append("name", "laoliu");
// 判断是否包含 key 为 name 的数据
console.log(formdata.has("name")); // true
// 判断是否包含 key 为 age 的数据
console.log(formdata.has("age")); // false

5、通过 delete(key) 可以删除数据

// 通过 FormData 构造函数创建一个空对象
var formdata = new FormData();
//通过 append() 方法在末尾追加 key 为 name 值为 laoliu 的数据
formdata.append("name","laoliu");
console.log(formdata.get("name")); // laoliu
// 删除 key 为 name 的值
formdata.delete("name");
console.log(formdata.get("name")); // null

参考引用:https://www.cnblogs.com/clj2017/p/9321652.html

五十一、返回、前进、刷新页面方法

window.location.reload() // 刷新

window.history.go(1) // 前进

window.history.go(-1) // 后退

window.history.forward() // 前进

window.history.back() // 后退 + 刷新

五十二、js 边界,分母为 0 问题

js 有哪些常见的边界问题?分母为 0、数组取数长度超界、ArrayBuffer 地址出界、null、undefined、undefined 中取值、递归出口出错 / 死循环、异步流 / timer 控制出错、最少不限与必填冲突问题等等

五十三、eval 中使用正则表达式对 \ 处理异常

const reg = eval('/^(([1-9]{1}\d*)|(0{1}))(\.\d{1,2})?$/');
// => /^(([1-9]{1}d*)|(0{1}))(.d{1,2})?$/

如果上面代码,eval 中的正则如果带 \ 则会被子去掉,解决方案如下:

const reg = eval('/^(([1-9]{1}\\d*)|(0{1}))(\\.\\d{1,2})?$/');
// => /^(([1-9]{1}\d*)|(0{1}))(\.\d{1,2})?$/

加多一个 \ 即可

五十三、eval 中使用正则表达式对 \ 处理异常

const reg = eval('/^(([1-9]{1}\d*)|(0{1}))(\.\d{1,2})?$/');
// => /^(([1-9]{1}d*)|(0{1}))(.d{1,2})?$/

如果上面代码,eval 中的正则如果带 \ 则会被子去掉,解决方案如下:

const reg = eval('/^(([1-9]{1}\\d*)|(0{1}))(\\.\\d{1,2})?$/');
// => /^(([1-9]{1}\d*)|(0{1}))(\.\d{1,2})?$/

加多一个 \ 即可

五十四、window.open 深度使用方法

      $(document).ready(function(){
          // 点击
          var myWindow = null;
          var myTimer = null;
          $("#btn").click(function(){
              myWindow = window.open('https://www.kt5.cn/fe', '_blank', 'top=150,left=150,scroll=yes,resizable=no,help=no,status=no,edge=sunken,height=500,width=800');
              myWindow.dialogArguments = {param1: '自定义参数1'};
              myTimer = setInterval(()=>{
                    if (myWindow.closed) {
                        clearInterval(myTimer);
                        alert(myWindow.dialogArguments.param1);
                    }
              }, 1000);
          });
      });

let windowObjectReference = window.open(strUrl, strWindowName, [strWindowFeatures]);
strUrl === 要在新打开的窗口中加载的URL。
strWindowName === 新窗口的名称。
strWindowFeatures === 一个可选参数,列出新窗口的特征(大小,位置,滚动条等)作为一个DOMString。

五十五、原生 Dom 节点类似 el.style.width=100 写法无效,建议全部用字符串如 el.style.width=”100px”

                const container = document.getElementById('container');
                container.style.width="100px"; // container.style.width=100 写法无效
				container.style.height="100px";