• 前端基础 碎片总结【持续更新】


    Github

    手写事件模型及事件代理/委托

    1. 捕获(低版本IE不支持捕获阶段)
    2. 目标
    3. 冒泡

    绑定事件的方法:

    target.addEventListener(eType, listener, useCapture);

    useCapture一般为false。为true时在捕获阶段触发。

    target.attachEvent(eType, listener); (仅IE8及以下版本浏览器)

    事件委托

    可以大量节省内存占用,减少事件注册

    可以实现当新增子对象时无需再次对其绑定事件,对于动态内容部分尤为合适

    原生JS事件委托

    关键代码

    obj.onclick = function(e){
        var ev = e || window.event;
        var target = ev.target || ev.srcElement;    //具体点到的目标,最内层
        var cTarget = currentTarget || this;    //对象this始终等于currentTarget
    }
    

    实现事件模型

    即写一个类或是一个模块,有两个函数,一个bind一个trigger,分别实现绑定事件和触发事件,核心需求就是可以对某一个事件名称绑定多个事件响应函数,然后触发这个事件名称时,依次按绑定顺序触发相应的响应函数。

    var Demo = (function(){
        var dirc = {};
        function bind(eType, func){
            if(typeof eType == "string" && typeof func == "function"){
                if(typeof dirc[eType] != "undefined"){
                    dirc[eType].push(func);
                }else{
                    dirc[eType] = [func];
                }
            }else{
                alert("bind传参有误");
            }
            console.log(dirc);
        }
    
        function trigger(eType){
            if(typeof dirc[eType] != "undefined"){
                for(var i=0; i < dirc[eType].length; i++){
                    dirc[eType][i]();
                }
            }
        }
    
        function unbind(eType){
            if(typeof dirc[eType] != "undefined"){
                delete dirc[eType];
            }
        }
    
        return {
            bind : bind,
            trigger: trigger,
            unbind : unbind
        }
    }());
    
    Demo.bind("hello",function(){alert("hello")});
    Demo.bind("hello",function(){alert("bbb")});
    Demo.trigger("hello");
    Demo.unbind("hello");
    Demo.trigger("hello");
    

    前端性能优化

    • CDN
    • 压缩静态文件
      • CSS Sprite
      • 图片压缩
    • CSS靠前/JS靠后
    • DOM操作放在一起
    • lazyload
    • 提高js的性能

    闭包原理及应用

    function fun(n,o) {
      console.log(o)
      return {
        fun:function(m){
          return fun(m,n);
        }
      };
    }
    var a = fun(0);  a.fun(1);  a.fun(2);  a.fun(3);    //undefined / ? / ? / ?
    var b = fun(0).fun(1).fun(2).fun(3);    //undefined / ? / ? / ?
    var c = fun(0).fun(1);  c.fun(2);  c.fun(3);    //undefined / ? / ? / ?
    

    链接

    手写Function.bind函数

    if (!Function.prototype.bind) {
        Function.prototype.bind = function(oThis) {
            if (typeof this !== "function") {
                // closest thing possible to the ECMAScript 5
                // internal IsCallable function
                throw new TypeError("TypeError");
            }
    
            var aArgs = Array.prototype.slice.call(arguments, 1),
                fToBind = this,
                fNOP = function() {},
                fBound = function() {
                    return fToBind.apply(this instanceof fNOP ? this : oThis || this,
                        aArgs.concat(Array.prototype.slice.call(arguments)));
                };
    
            fNOP.prototype = this.prototype;
            fBound.prototype = new fNOP();
    
            return fBound;
        };
    }
    

    排序算法

    快速排序(去重)

    //第一种:
    //找到一个基准值,左边找到大于基准值,右边找到小于基准值的同时,左右换位。继续遍历。
    function sort(arr){
        return quickSort2(arr,0,arr.length-1);
        function quickSort2(arr,l,r){            
            if(l<r){         
                var mid=arr[parseInt((l+r)/2)],i=l-1,j=r+1;         
                while(true){
                    while(arr[++i]<mid);
                    while(arr[--j]>mid);             
                    if(i>=j)break;
                    var temp=arr[i];
                    arr[i]=arr[j];
                    arr[j]=temp;
                }       
                quickSort2(arr,l,i-1);
                quickSort2(arr,j+1,r);
            }
            return arr;
        }
    }
    
    //第二种:
    //遍历数组, 小的放基准值左边,大的放右边,递归
    var quickSort = function(arr) {
        if (arr.length < 2) {
            return arr;
        }
        var key = arr[0],
            leftPart = [],
            rightPart = [];
        for (var i = 0; i < arr.length; i++) {
            if (arr[i] < key) {
                leftPart.push(arr[i]);
            }
            if (arr[i] > key){
                rightPart.push(arr[i]);
            }
            //不去重的话可以在此增加判断,等于key的push到middle数组,最后拼接进去。
        };
        return quickSort(leftPart).concat([key],quickSort(rightPart));
    }
    

    冒泡排序

    function bubbleSort(arr){
        var result = arr,
            len = result.length;
        for(var i=0; i < len; i++){
            for(var j=0; j < len-1-i; j++){
                console.log(++sss);
                if(result[j]>result[j+1]){
                    var temp = result[j];
                    result[j] = result[j+1];
                    result[j+1] = temp;
                }
            }
        }
        return result;
    }
    

    去重

    function unique(arr){
        var result=[],
            record = {};    //记录每个元素出现的次数
        for(var i=0; i< arr.length; i++){
            if(record[arr[i]]){
                record[arr[i]]++;
            }else{
                result.push(arr[i]);
                record[arr[i]]=1;
            }
        }
        return record;
    }
    

    JS的定义提升

    function Foo() {
        getName = function() {
            alert(1);
        };
        return this;
    }
    Foo.getName = function() {
        alert(2);
    };
    Foo.prototype.getName = function() {
        alert(3);
    };
    var getName = function() {
        alert(4);
    };
    
    function getName() {
        alert(5);
    }
    
    //请写出以下输出结果:
    Foo.getName();
    getName();
    Foo().getName();
    getName();
    new Foo.getName();
    new Foo().getName();
    new new Foo().getName();
    

    链接

    跨域问题

    JavaScript跨域总结与解决办法

    跨域-知识

    跨域资源共享的10种方式

    1、document.domain+iframe的设置

    对于主域相同而子域不同的例子,试用该方法。

    xxx.a.com上的a.html

    document.domain = 'a.com';
    var ifr = document.createElement('iframe');
    ifr.src = 'http://script.a.com/b.html';
    ifr.style.display = 'none';
    document.body.appendChild(ifr);
    ifr.onload = function(){
        var doc = ifr.contentDocument || ifr.contentWindow.document;
        // 在这里操纵b.html
        alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue);
    };
    

    script.a.com上的b.html

    
    document.domain = 'a.com';
    

    问题:

    1、安全性,当一个站点(b.a.com)被攻击后,另一个站点(c.a.com)会引起安全漏洞。

    2、如果一个页面中引入多个iframe,要想能够操作所有iframe,必须都得设置相同domain。

    2、JSONP

    思路

    动态创建script标签,src带参数请求其它地址。

    返回后进行操作。

    最后要销毁。

    3、利用iframe和location.hash

    a.html和c.html同域
    b.html不同域
    实现a.html与b.html通信
    
    a.html > b.html > c.html
    

    HTML5 postMessage

    //a.html
    <iframe id="ifr" src="b.com/index.html"></iframe>
    <script type="text/javascript">
    window.onload = function() {
        var ifr = document.getElementById('ifr');
        var targetOrigin = 'http://b.com';  // 若写成'http://b.com/c/proxy.html'效果一样
                                            // 若写成'http://c.com'就不会执行postMessage了
        ifr.contentWindow.postMessage('I was there!', targetOrigin);
    };
    </script>
    
    //b.html
    <script type="text/javascript">
        window.addEventListener('message', function(event){
            // 通过origin属性判断消息来源地址
            if (event.origin == 'http://a.com') {
                alert(event.data);    // 弹出"I was there!"
                alert(event.source);  // 对a.com、index.html中window对象的引用
                                      // 但由于同源策略,这里event.source不可以访问window对象
            }
        }, false);
    </script>
    

    window.name跨域

    a,b,c三个页面. a,c同域, b不同域

    a里面添加iframe,设置src为b页面.b页面里面修改window.name,也就是iframe里面的window.name,

    第一次onload时,将iframe里的src改成c的地址.此时c跟a同域,可以传递window.name.

    document.domain+iframe的设置 (用于主域相同,子域不同的情况)

    正则表达式

    方法

        var reg = /w+/g;
        reg.test(str);
        str.match(reg);
    

    规则

    /d    [0-9]                   匹配数字
    /D    [^0-9]                  匹配非数字字符 
    /s    [ /n/r/t/f/x0B]         匹配一个空白字符 
    /S    [^ /n/r/t/f/x0B]        匹配一个非空白字符 
    /w    [a-zA-Z0-9_]            匹配字母数字和下划线 
    /W    [^a-zA-Z0-9_]           匹配除字母数字下划线之外的字符 
    
    
    *     匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。 * 等价于{0,}。 
    +     匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。 
    ?     匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。 
    {n}   n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。 
    {n,}  n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。
          'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。
    {n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。刘, "o{1,3}" 将匹配 "fooooood" 中的前三个 o。
        'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。
    

    字符串操作

    concat() – 将两个或多个字符的文本组合起来,返回一个新的字符串。 
    indexOf() – 返回字符串中一个子串第一处出现的索引。如果没有匹配项,返回 -1 。 
    charAt() – 返回指定位置的字符。 
    lastIndexOf() – 返回字符串中一个子串最后一处出现的索引,如果没有匹配项,返回 -1 。 
    match() – 检查一个字符串是否匹配一个正则表达式。 
    substring() – 返回字符串的一个子串。传入参数是起始位置和结束位置。 
    substr() – 返回字符串的一个子串。传入参数是起始位置和字符串长度。(不建议使用) 
    replace() – 用来查找匹配一个正则表达式的字符串,然后使用新字符串代替匹配的字符串。 
    search() – 执行一个正则表达式匹配查找。如果查找成功,返回字符串中匹配的索引值。否则返回 -1 。 
    slice() – 提取字符串的一部分,并返回一个新字符串。 
    split() – 通过将字符串划分成子串,将一个字符串做成一个字符串数组。 
    length – 返回字符串的长度,所谓字符串的长度是指其包含的字符的个数。 
    toLowerCase() – 将整个字符串转成小写字母。 
    toUpperCase() – 将整个字符串转成大写字母。
    

    数组操作

    concat() – 连接两个或更多的数组,并返回结果。
    join() – 把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。
    pop() – 删除并返回数组的最后一个元素
    push() – 向数组的末尾添加一个或更多元素,并返回新的长度。
    reverse() – 颠倒数组中元素的顺序。
    shift() – 删除并返回数组的第一个元素
    unshift() – 向数组的开头添加一个或更多元素,并返回新的长度。
    slice() – 从某个已有的数组返回选定的元素
    sort() – 对数组的元素进行排序
    splice() – 删除元素,并向数组添加新元素。
    toSource() – 返回该对象的源代码。
    toString() – 把数组转换为字符串,并返回结果。
    toLocaleString() – 把数组转换为本地数组,并返回结果。
    valueOf() – 返回数组对象的原始值
    

    字符串和数组操作应用

    //获取url参数
    var getUrlPara = function(){
        var arr = window.location.search.substring(1).split("&"),
            result = {};
        for(var i=0; i < arr.length; i++){
            result[arr[i].split("=")[0]] = arr[i].split("=")[1];
        }
        return result;
    }
    

    设计模式

    (这一块得回家看笔记...)

    函数节流

    通过setTimeout和clearTimeout对于频繁执行的函数进行延时处理。

    例如: onresize, onscroll 还有drag之类的。(为避免由于频率过高导致一直都不执行,可以设置一个必然触发执行的时间间隔)

    var throttle = function(fn, delay){
        var timer = null;
        return function(){
            var context = this, args = arguments;
            clearTimeout(timer);
            timer = setTimeout(function(){
                fn.apply(context, args);
            }, delay);
        };
     };
    
    
    var throttleV2 = function(fn, delay, mustRunDelay){
        var timer = null;
        var t_start;
        return function(){
            var context = this, args = arguments, t_curr = +new Date();
            clearTimeout(timer);
            if(!t_start){
                t_start = t_curr;
            }
            if(t_curr - t_start >= mustRunDelay){
                fn.apply(context, args);
                t_start = t_curr;
            }
            else {
                timer = setTimeout(function(){
                    fn.apply(context, args);
                }, delay);
            }
        };
     };
    
  • 相关阅读:
    【Henu ACM Round#20 B】Contest
    【Henu ACM Round#20 A】 Fancy Fence
    【Henu ACM Round#19 F】Dispute
    【Henu ACM Round#19 E】 Om Nom and Candies
    【Henu ACM Round#19 D】 Points on Line
    【Henu ACM Round#19 C】 Developing Skills
    【Henu ACM Round#19 B】 Luxurious Houses
    【Henu ACM Round#19 A】 Vasya the Hipster
    【Codeforces Round #460 (Div. 2) D】Substring
    JQuery中attr ,html,text,val,的一些用法
  • 原文地址:https://www.cnblogs.com/kyles/p/5239182.html
Copyright © 2020-2023  润新知