JS基础挖掘

一、普通函数与自执行函数的区别

例1:

        $('#btn').click(function(){
            $('.box').animate({
            width:"500px",
            height:"200px"
        },2000,function(){
            console.log('执行完成了');
        })
        });

例2:

        $('#btn').click(
            $('.box').animate({
            width:"500px",
            height:"200px"
        },2000,function(){
            console.log('执行完成了');
        })
        );

思考:在手撸jQuery中遇到了这个问题,普通函数与自执行函数的区别我当然知道,一个需要调用或触发才能执行,一个自动执行。当时突然蒙圈了一下,不知道什么叫做自执行函数了,不是不明白他的定义,而是对于它的使用位置方式产生了疑惑,典型的眼高手低。
例1与例2的代码是基本一样的,想要达到的要求是点击一个按钮,盒子大小发生变化,同时控制台输出“执行完成了这句话”
例2是我自己手撸的,测试发现,不需要点击就自动执行了,当时陷入了误区,后面才判断出来这个肯定是自执行了,因为控制台并没有报错。既然自执行,那么必然click里面是一个自执行函数,整个click监听事件并没有起作用,对比例1可以发现,例1是给click事件绑定了一个回调函数,等点击事件触发后,才会执行回调函数中的内容,出错原因就在这里。

二、js下获取某个父元素的子元素数量,并给每个子元素绑定事件(2021-05-12)

li{
            width: 100px;
            height: 60px;
            background-color: pink;
            margin-top: 10px;
            list-style: none;
            text-align: center;
            line-height: 60px;
            font-size: 30px;
        }
<script src="./jquery.js"></script>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
    <script>
        //js下获取某个父元素的子元素数量,并给每个子元素绑定事件==>什么元素不重要,子元素数量也不重要,绑定什么事件也不重要
        /* 第一种 原生方式 */
        let ulObj = document.querySelector('ul');
        console.log(ulObj.children.length);//输出的是HTMLCollection 一个集合的形式,伪数组,只有数组的length属性,没有相应的方法
        console.log(Array.from(ulObj.children));//利用Array.from()将伪数组转成真数组,这时可以使用其中的方法了
        /* Array.from(ulObj.children).forEach(v=>{
            v.addEventListener("click",()=>{
                console.log(v.innerHTML);
            })
        }) */
        /* 第二种 利用JQuery方式 */  //利用children或find后代选择器,使用on绑定
        
        console.log($('ul').children());
        $('ul').children().on('click',function(){
            console.log(this.innerHTML);
        })
    </script>

三、正则表达式

question:1: sadfasf2: fsahdfiewhi3: fdgajgnas15: 4645das5faadsfi4: asidnaskl

需要正则的问题如上,需要匹配的就是数字+英文冒号+一个空格,将其变为一个英文逗号(注:此问题从数组对象中提炼出来)
先复习下正则相关知识:

正则表达式
一、转义符
\d 表示0-9数字
\D 表示非数字
\w 数字字母下划线
\W 非数字字母下划线
\s 空格
\S 非空格


二、量词
* 表示至少0次
+ 表示至少一次
?表示最多一次
{n} 表示固定n次
{n,} 表示至少n次
{n,m} 表示n到m次之间的任何次数都可以接受;至少n次,至多m次


三、修饰符
g 全局匹配
i 忽略大小写


四、或
| 表示或


五、子集
( ) 表示子集


六、范围符
- 表示范围


七、中元符
[ ] 用来标记范围,内部所有组成都是或的关系

ok,首先是匹配1到2位的数字 \d{1,2},接着是英文的冒号\W{1},最后是一个空格\s{1} 如果想更安全,更准确,可以加上开始(^)与结束符($),结合起来写就是:^\d{1,2}\W{1}\s{1}$

正则只有常用,才会不经意间记住,特意去记反而没有什么用户,还有记住他们的特点和区别也非常重要。

四、前端经常出现的兼容问题

页面滚动条距离顶部的距离
	document.documentElement.scrollTop || document.body.scrollTop

页面滚动条距离左边的距离
	document.documentElement.scrollLeft || document.body.scrollLeft

获取当前网页可显示区域宽度
	document.documentElement.clientWidth || window.innerWidth

获取当前网页可显示区域高度问题:ie有兼容性问题解决:
	document.documentElement.clientHeight ||  window.innerHeight

获取event事件	event需要逐层传递,不要疏忽外部的function!!!!!
 	IE中: window.event
	正常浏览器中:对象.on事件 = function(event){}

		 兼容方式:						
  			  function fn(eve){					
       				 var e = eve || window.event;			
  			  }	


		eg: document.onclick = function(eve){
			var e = eve || window.event;
			}




获取按下的键码
 var keyC = eve.keyCode || eve.which

	IE只有keyCode属性,
	FireFox中有which和charCode属性,
	Opera中有keyCode和which属性,
	Chrome中有keyCode、which和charCode属性




获取非行内样式(兼容问题)     getComputedStyle(obj).height
    function getStyle(obj,attr){     获取非行间样式,obj是对象,attr是值
        if(obj.currentStyle){        针对ie获取非行间样式
            return obj.currentStyle[attr];
        }else{
            return getComputedStyle(obj,false)[attr]; //针对非ie
        };
    };



阻止默认事件
	e.preventDefault();
	e.returnValue = false;
	return false

    处理兼容方式
    if( e.preventDefault ){
        e.preventDefault();
    }else{
        e.returnValue = false;
    }
	


	或者直接
		obj.onclick = function(){
			return false;
		}

冒泡:从下往上(从里往外)
捕获:从上往下(从外往内)


阻止事件冒泡
	eve.stopPropagation(); 
	eve.cancelBubble = true;        //兼容IE

if(eve.stopPropagation){
      eve.stopPropagation()
    }else{
	eve.cancelBubble = true;
           }

事件委托
	通过e.target获取触发事件的事件源
	利用事件冒泡原理,将绑定在多个子元素身上的相同事件,绑定在页面上现存的父元素身上。

	var e = eve || window.event;
	var target = e.target || e.srcElement;


		oul.onclick = function(eve){
             	    var e = eve || window.event;
                    var target = e.target || e.srcElement;
                   if(target.nodeName == "LI"){
                       console.log(target.innerHTML);
                    }  
                }


DOM2级事件绑定
事件监听器
	  非IE下
		obj.addEventListener('click',fn,false);
    		obj.removeEventListener('click',fn ,false);

	 IE下:只有冒泡阶段,所以没有第三个参数;(这里的事件名需要加on)
		obj.attachEvent();
    		obj.detachEvent() ;


兼容问题解决:
	1.封装成对象的方式
		  var EventUtil={
        addHandler:function(DOM,EventType,fn){
            if(DOM.addEventListener){
                DOM.addEventListener(EventType,fn,false);
            }else if(DOM.attachEvent){
                DOM.attachEvent('on'+EventType,fn)
            }else{
                DOM['on'+EventType]=fn
            }
        },
        removeHandler:function(DOM,EventType,fn){
            if(DOM.removeEventListener){
                DOM.removeEventListener(EventType,fn,false)
            }else if(DOM.detachEvent){
                DOM.detachEvent('on'+EventType,fn)
            }else{
                DOM['on'+EventType]=null;
            }
        }
    }

	2.封装成两个函数的方式
    function addEvent(obj,inci,back){
        if(obj.addEventListener){
            obj.addEventListener(inci,back);
        }else if(obj.attachEvent){
            obj.attachEvent("on" + inci,back);
        }else{
            obj["on"+inci] = back;
        }
    }
          
    function removeEvent(obj,inci,back){
        if(obj.removeEventListener){
            obj.removeEventListener(inci,back,false);
        }else if(obj.detachEvent){
            obj.detachEvent("on" + inci,back);
        }else{
            obj["on"+inci] = null;
        }
    }



浏览器元素的尺寸

offsetParent:获取元素的最近的具有定位属性(absolute或者relative)的父级元素。
	      如果都没有则回body

offsetLeft:表示元素的 左外边框   至offsetParent元素的   左内边框   之间的像素距离

offsetTop:表示元素的  上外边框   至offsetParent元素的   上内边框   之间的像素距离

offsetWidth/offsetHeight:元素本身实际宽度/高度
	offsetWidth = width + 左右padding + 左右border
	offsetHeiht = height + 上下padding + 上下border

clientWidth/clientHeight:元素本身可视宽度/高度(客户端)
	clientWidth  元素视窗宽度  clientWidth = width  +  左右padding
	clientHeight  元素视窗高度 clientHeight = height + 上下padding 


检测相对于事件源的位置:offsetX和offsetY
	当鼠标事件发生时,鼠标相对于事件发生元素左上角的位置


检测相对于浏览器的位置:clientX和clientY
	当鼠标事件发生时,鼠标相对于浏览器左上角的位置

检测相对于屏幕的位置:screenX和screenY
	 当鼠标事件发生时,鼠标相对于屏幕左上角的位置

检测相对于文档的位置:pageX和pageY	带滚动条距离
 当鼠标事件发生时,鼠标相对于文档左上角的位置。(IE7/8无)(类似于event.clientX和event.clientY)

2021-05-13

五、js报错Cannot read property ‘innerHTML’ of underfined

报错翻译:无法读取undefined的innerHTML属性
事实上,undefined没有任何属性可以供读取,因此这个报错要考虑是否是有标签节点没有被获取到,因此输出的值是undefined,所以找不到innerHTML属性

example:

	//省略前置代码
	<ul>
        <li class="user">1</li>
        <li class="user">2</li>
        <li>3</li>
        <li class="user">4</li>
        <li class="user">5</li>
        //简化li标签内容,实际工作场景中每个li标签至少3-5层层级嵌套
    </ul>
    //省略后序代码

问题:先获取父级元素ul节点,通过遍历其子节点,理论上可以拿到每一个innerHTML与innerText的值,但是无法获取到,反而是报上述错误。。。
排查解决思路:

1.排除是js代码异步加载问题:将js代码放到整个页面最后加载或使用Window.onload方法
2.检查遍历所有子级li标签时是否是都有指定的innerHTML与innerText,js代码加载过程中,只要出现一个未知错误,整个遍历过程便结束,程序代码也会停止执行,抛出对应的错误!

经检查,发现是第二种情况,补一个user类名即可。

六、干掉父元素下所有元素的最简洁方法

//1.js原生方法
父元素.innerHTML = ""; 
//2.jQuery封装方法
$(父元素).empty();//利用empty方法可以直接排空父元素
//与此对应的是remove方法,直接将整个父元素包括其在内的后代元素全部干掉

七、快排一个数组对象商品列表(对象属性有销量/新旧价格/评论量等)

let arr=[{id:1,num:456,oldPrice:852,newPrice:9.9,comment:866},{id:2,num:358,oldPrice:999,newPrice:9.9,comment:583}]

根据不同要求,进行销量/价格评论数量/综合等排序(详情参考某宝形式)

        let arr=[{id:1,num:456,oldPrice:852,newPrice:9.9,comment:866},{id:2,num:358,oldPrice:999,newPrice:9.9,comment:583}]
        let arr1=[];
        arr.forEach((v,k)=>{
            arr1.push([v.id,v.num]);
        })
        console.log(arr1);//带有商品id与商品销量的二维数组===>乱序
        arr1.sort(function(a,b){
            return a[1] -b[1];
        })
        console.log(arr1);//根据数量进行升序

这里拿销量做例子,形成二维数组,进行升序排列,同理,可以形成更多维数组,对比更多不同属性,最后靠商品的唯一标识符区别即可,然后进行商品的重新渲染。

八、localStorage与JSON的不解之缘

		JSON.stringify()//对象转为字符串
        JSON.parse()//字符串解析为json对象
        localStorage.setItem()//设置localStorage,第一个参数是想要设置的key,第二个参数是想要设置的value(可以是对象)
        localStorage.getItem()//获取localStorage,接收一个参数,需要获取的key名

后端传给前端的数据一般是json格式的,这就导致前端在拿到数据想放入localStorage时是无法直接用的,强行设置的话,会显示object对象,需要借助JSON.stringify存储到localStorage里面,拿出来时也要反向parse一下

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值