js相关笔记(十三)

1.定义Date日期对象的四种方式

//默认当前时间的定义 方式
    var date1 = new Date();
    console.log(date1);


    //指定某个时间的定义 方式
    var date2 = new Date("2019/1/31 15:48:20");//兼容最强
    console.log(date2);


    //直接指定字面量  但是兼容性不是很好 因为每个浏览器渲染的Date对象的字面量可能不一样
    var date3 = new Date("Thu Jan 31 2019 15:48:20 GMT+0800 (中国标准时间)");
    console.log(date3);


    //指定年月日的方式 来定义
    var date4 = new Date(2019, 1, 31);
    console.log(date4);



2.操作日期对象

console.log(date1.getDate());        //     获取日 1-31
    console.log(date1.getDay());         //     获取星期 0-6(0代表周日)
    console.log(date1.getMonth());       //   获取月 0-11(1月从0开始)
    console.log(date1.getFullYear());        //    获取完整年份(浏览器都支持)
    console.log(date1.getHours());       //获取小时 0-23
    console.log(date1.getMinutes());         //获取分钟 0-59
    console.log(date1.getSeconds());         //获取秒  0-59
    console.log(date1.getMilliseconds());        // 获取毫秒 (1s = 1000ms)
    console.log(date1.getTime());        //返回累计毫秒数(从1970/1/1午夜)



3.为什么时间都是从1970/1/1午夜开始的,因为那是一个纪念的日子,有一个实验室,c语言和unix系统都是从那个实验室出来的,unix是收费的,linux是开源的,诺贝尔的获得者有七八个都是这个实验室的,后台他们把这个1970/1/1午夜被制定成了一个计算机时间的基本点,后面的人一直沿用至今。


4.返回当前距离时间基本点的毫秒数的四种方式

    var date = Date.now();
    console.log(date);
    var date = +new Date();
    console.log(date);
    var date = new Date().getTime();
    console.log(date);
    var date = new Date().valueOf();
    console.log(date);



5.获取页面代码执行的毫秒值

//获取代码开始执行之前的时间的毫秒数
    var start=Date.now();


//执行的代码
//    //开始进行1加到100000之间的运算
//    var sum=0;
//    for(var i=1;i<=100000;i++){
//        sum+=i;
//    }


 //获取代码结束执行之后的时间的毫秒数
    var end=Date.now();


console.log(end-start);//定义代码执行的毫秒数



5.简单数据类型无法绑定属性和方法,字符串之所以能够使用length属性和indexOf方法,完全是因为,当你使用字符串.属性或者方法的时候,底层会进行隐式转换复杂类型,将简单的字符串转换成了String对象了,所以才能够使用length属性和indexOf方法,用完之后会再转换回来。


6.真正的String对象的实例内部其实是这样的【
    //创建String对象实例
    var strobj=new String("abcdefg");
   //打印该对象实例
    console.log(strobj);//{0: "a",1: "b",2: "c",3: "d",4: "e",5: "f",6: "g", length: 7,[[PrimitiveValue]]: "abcdefg"}
  每一个字符串都有对应的数字作为key,所以能够使用[]的方式来访问字符串中的每个字符。



7.for..in 遍历对象的时候只会遍历,允许让你访问的属性的名称,也就是key,你可以通过对象名[key]来获取value,也就是属性值。。


8.字符串获取单个字符的方式除了[]这种方式之外(IE678不支持这种方式),还能够使用charAt()方法,方法中的参数与[]中的参数一样,也是通过索引(key)来获取值(value)的,如果你想获取字符串中某个值得unicode码(十进制纯数字)的话,可以使用charCodeAt(key)方法,也是传索引,内部会先调用charAt(key)获取值,然后再进行unicode码的转换,数组的sort方法底层默认就是使用unicode码来进行比较的。【
var str="abcdefg";
    console.log(str);//abcdefg
    //使用[]方式来遍历
    for(var i=0;i<str.length;i++){
        console.log(str[i]);
    }
    //使用charAt方法来遍历  根据索引找到字符串 也是根据String对象中数字的key来找到字符
    for(var i=0;i<str.length;i++){
        console.log(str.charAt(i));
    }
    //使用charCodeA方法来遍历  也是根据索引找到字符串
    // 然后再进行unicode码转换,最终变成了变成了数字 48代表1 65代表A 97代表a
    for(var i=0;i<str.length;i++){
        console.log(str.charCodeAt(i));
    }



9.获取一条字符串的字符占位的长度(不是字符串的长度),可以使用charCodeAt()方法,unicode码在0-127中的话,所占的字符占位长度为1,除此之外的字符占位长度为2。【
    function getCharlength(str) {
        var count = 0;
        for (var i = 0; i < str.length; i++) {
            //占一个字符位的字符 unicode码在0-127
            // 其它的占两个及两个以上的字符位的字符 unicode码不在0-127之间
            if (str.charCodeAt(i) < 128 && str.charCodeAt(i) >= 0) {
                count++;
            } else {
                count += 2;
            }
        }
        return count;
    }



10.基本包装类型 String/Number/Boolean对应了string/number/boolean,所以当这些简单数据类型调用方法或者属性时,底层都会去转换为复杂数据类型的对象实例来操作,操作完毕之后会再转换回去,相当于底层做了包装一样。


11.操作字符串的方法 
◆charAt:根据字符串位置的索引返回指定字符
◆charCodeAt:根据字符串位置的索引返回指定字符的十进制的unicode编码的数值。
◆indexOf:根据字符串的字符返回索引值, 从前往后搜索。
◆lastIndexOf:根据字符串的字符返回索引值,从后往前搜索
◆encodeURIComponent:对url地址进行uri编码,他是window对象的方法,方法参数是字符串。
◆decodeURICompoent:对uri编码后的url进行解码,他是window对象的方法,方法参数是字符串。
◆concat:连接两个字符串,+的底层用的就是这个方法
◆slice:截取划分,和数组的silce方法类似,也是指定起始索引和结束索引,来截取原字符串返回新字符串,也是截取时包括左边的索引不包括右边的索引,索引为负数则为字符串的长度加上这个负数索引,如果起始索引大于结束索引则会返回空字符串,如果只有一个起始索引则会截取到最后。
◆substr:截取,和数组的splice方法类似,只不过这个方法只有截取没有替换,指定起始索引和要截取的长度来截取字符串,长度过大就直接等于字符串的长度,长度为负数则为0,索引为负数则字符串的长度加上这个负数索引。
◆substring:截取划分,和字符串的slice方法类似,只不过不同的地方是,索引为负数,那么直接返回全部字符串,如果起始索引大于结束索引,就会智能替换,把小的索引作为起始索引,大的索引作为结束索引。
◆trim:去掉字符串开头部分与结束部分的空格(IE678不支持,但是可以自己封装)。
◆replace:替换原字符串返回新字符串,第一个参数是原字符串中的某一段字符串,第二个参数是替换掉原字符串中的某一段字符串的字符串,使用str.replace(/\s/gi,"")可以替换掉所有的空格,这种方式叫做正则表达式。


12.字符串与数组之间的相互转换
◆join与split方法,数组通过join方法变成字符串,字符串通过split方法变成数组

//数组
    var arr=["吕布","赵云","关羽","张飞","刘备"];
    console.log(arr);//["吕布", "赵云", "关羽", "张飞", "刘备"]
  //数组通过分隔符号连接成了字符串
    console.log(arr.join("|"));//吕布|赵云|关羽|张飞|刘备
    //字符串
    var str="吕布|赵云|关羽|张飞|刘备";
    console.log(str);//吕布|赵云|关羽|张飞|刘备
    //如果split方法中的参数为空字符串,那么就会对字符串中每一个字符进行分割然后放入数组中,否做就会以分割符号来分割每一段字符串(不包括分隔符)然后放入数组中。
    console.log(str.split("|"));//["吕布", "赵云", "关羽", "张飞", "刘备"]



13.字符串中的字母大小写相互转换
◆str.toLowerCase();//将str变量中的字母无论大小写都变成小写的字母,这个方法会返回新的字符串。
◆str.toUpperCase();//将str变量中的字母无论大小写都变成大写的字母,这个方法会返回新的字符串。


14.字符串中的转换为html标签字符串的方法
◆anchor()方法:    "我是一个锚点".anchor("mao");等于<a name="mao">我是一个锚点</a>
◆link()方法:   "我是一个超链接".link("http://www.baidu.com");等<a href="http://www.baidu.com">我是一个超链接</a>(记住这个)
◆其它不常用的标签【
 var str="你好";
    console.log(str.anchor());//<a name="undefined">你好</a>
    console.log(str.big());// <big>你好</big>
    console.log(str.sub());// <sub>你好</sub>
    console.log(str.sup());// <sup>你好</sup>
    console.log(str.link());//<a href="undefined">你好</a>
    console.log(str.bold());//<b>你好</b>



15.数学对象的方法
◆Math.abs(num);num取绝对值
◆Math.pow(num1,num2);num1的num2次方
◆Math.power(num1,num2);num1的num2次幂
◆Math.sqrt(num);num开平方,相当于Math.power(num,2);
◆Math.sin(num);num的正弦
◆Math.cos(num);num的余弦


16.九尺龙泉万卷书,上天生我意如何。不能报国平天下,枉为男儿大丈夫。


17.事件绑定的方式
◆对象.事件名=匿名函数/普通函数【
    //第一种方式 使用对象.属性的方式定义的,后面定义的事件会覆盖掉前面的
    btn1.onclick=function(){
        console.log("九尺龙泉万卷书,上天生我意何如。");
    }
    btn1.onclick=function(){
        console.log("不能报国平天下,枉为男儿大丈夫。");
    }

◆对象[事件名]=匿名函数/普通函数【
//第二种方式 使用对象[属性名]的方式定义的,后面定义的事件会覆盖掉前面的
    btn2["onclick"]=function(){
        console.log("九尺龙泉万卷书,上天生我意何如。");
    }
    btn2["onclick"]=function(){
        console.log("不能报国平天下,枉为男儿大丈夫。");
    }

◆对象.addEventListener(event,fn)或者对象.attachEvent(fullevent,fn)【
//第三种方式 底层原理是不断保存每次事件的地址,递归执行或者循环执行方法 所以不会被覆盖掉
    //使用addEventListener更加有助于团队开发  因为前面两种方式都会采取最后面的覆盖掉前面的 但是IE678不支持
    btn3.addEventListener("click",fn1);//直接写click 底层会加on
    btn3.addEventListener("click",fn2);
    //使用attachEvent 只有IE678支持
//    btn3.attachEvent("onclick",fn1);//直接写onclick 底层不会再加on
//    btn3.attachEvent("onclick",fn2);

★addEventListener与attachEvent区别在于, 在前者中用this关键字代表是的事件源对象,在后者中用this关键字代表的是window对象,内部机制不一样,在IE678中不能使用addEventListener来绑定事件,只能使用attachEvent绑定事件,但是在IE678之后addEventListener取代了attachEvent,因为内部机制进行了更新,更新的地方是,将函数里面的this不代表当前事件源的bug修改了。


18.事件解绑的方式
◆对象.事件=null【
//针对第一种绑定的方式的解绑
    btn1.onclick=null;

◆对象[事件]=null【
//针对第二种绑定的方式的解绑
    btn1["onclick"]=null;

◆对象.removeEventListener(event,fn)或者对象.detachEvent(fullevent,fn)【
//针对第三种绑定方式的解绑
    btn3.removeEventListener("click",fn1);//解绑单击事件中的fn1
    btn3.removeEventListener("click",fn2);//解绑单击事件中的fn2
    //兼容IE678 因为只有IE678支持
//    btn3.detachEvent("click",fn1)////解绑单击事件中的fn1
//    btn3.detachEvent("click",fn2)////解绑单击事件中的fn2



19.事件的本质
◆事件的本质就是方法
◆方法的定义方式有三种:
◇function fn(){};
◇var fn=function(){};
◇var fn=new Function("");
◆事件是属于一个对象自己的方法
◇对象.methoed=fn;
◇对象.methoed=function(){};
◇对象.methoed=new Function("");
◆addEventListener与attachEvent可以实现多个方法的绑定,实际原理是将前一个事件如(onclick)的地址存起来,然后重新给这个事件赋值,先调用前一个事件如(onclick)的地址执行的方法,然后再调用你之后绑定的方法【
//addEventListener的底层原理
    function addEvent(action,fn,element){
        //把上一个事件的方法指针存起来
        var tempEvent=element["on"+action];
        element["on"+action]=function(){
            //如果之前的事件已经绑定了方法
            if(tempEvent){
                //那么先执行之前的事件中的代码 再继续下面的
//                console.log(tempEvent);
                tempEvent();
            }
            //执行绑定的代码
            fn();
        }
    }

◆addEventListener与attachEvent的原理远远不止上面的那么简单,其实它还进行了将每一个方法存到一个数组里面的操作,当每绑定一个方法,都会进行判断,是有已经有了这个方法,如果有了就不会再绑定重复的方法【
//添加事件
    function addEvent(action,fn,element){
        //判断当前事件对象中是否有这个行为的数组
        if(!eventObj[action]){
            //没有就创建
            eventObj[action]=[];
        }
        //判断函数数组中是否有这个函数
        for(var i=0;i<eventObj[action].length;i++){
            if(eventObj[action][i]===fn){
                return;
            }
        }
//        //把当前的事件存到数组中 ,然后等到
//        if(element["on"+action]){
//
//        }
        //有的话每次添加方法都是放入一个事件对象的这种行为数组中(栈中)
        eventObj[action].push(fn);
        element["on"+action]=function(){
            //遍历栈中的方法 按照顺序循环执行
            for(var i=0;i<eventObj[action].length;i++){
                //IE 678使用的是  attachEvent 原理就是这样的
//                eventObj[action][i]();


                //IE678之后用的是这个 addEventListener 原理就是这样的
                //这样就把方法中的this转换成了当前的对象
                element.actionMethod=eventObj[action][i];
                //由当前对象来调用
                element.actionMethod();
            }
        }
    }

★将以上两种结合起来就是系统的addEventListener和attachEvent原理,因为第一种和第二种加起来就能够兼容btn1.onclick=function(){},把它给添加到事件队列中去。
◆removeEventListener与detachEvent的简单原理【
    //移除事件
    function removeEvent(action,fn,element){
        //IE678以上
        //根据对象找索引 从后往前找,因为添加的时候是从后面添加的
//        var index= eventObj[action].lastIndexOf(fn);


        //直接切掉这个对象
//        eventObj[action].splice(index,1);


        //为了兼容IE678 因为indexOf和lastIndexOf方法不能用了
        for(var i=eventObj[action].length-1;i>=0;i--){
            //判断对象是否一致
            if(eventObj[action][i]===fn){
                eventObj[action].splice(i,1);
                return;
            }
        }
    }

★removeEventListener与detachEvent的原理不止上面那么简单,上面的是种实现的方式,但是不是最好的实现方式,因为我做的这种实现其实 和系统的实现无不干扰,其实系统的removeEventListener与detachEvent貌似还是另一套机制,当你使用对象.事件=null;的时候,无法去除你用addEventListener和attachEvent绑定的事件,就像你用removeEventListener与detachEvent也无法去除对象.事件=方法名;但是addEventListener和attachEvent绑定的事件可以获取到对象.事件=方法名;绑定的事件,并且还会吧这种方式绑定的事件存到自己的队列里面去,但是无法移除,只能添加。
posted @ 2018-06-10 18:06  我叫贾文利  阅读(137)  评论(0编辑  收藏  举报