美文网首页
js经典题目

js经典题目

作者: lonelyRon | 来源:发表于2018-04-21 13:10 被阅读0次

    1闭包

    链接:学习Javascript闭包(Closure)

    function close(){
        var arr = [1,2,3,4]
        for( var i = 0; i < arr.length; i ++){
            setTimeout(function(){
                console.log(i)
            })
        }
    } 
    close(arr)//4,4,4,4
    

    setTimeout在js单线程中只是放在队列中并未调用,等到主线程任务完成才会执行
    链接:JavaScrip同步、异步、回调执行顺序之经典闭包setTimeout分析

    function close(){
        var arr = [1,2,3,4];
        for( var i = 0; i < arr.length; i ++){
            (function(i){
                setTimeout(function(){
                    console.log(i)
                })
        })(i)
    }
    } 
    close()//0,1,2,3
    

    立即执行函数在每一次循环中执行setTimeout函数并将值传到setTimeout函数中

    function close(){
        var arr = [1,2,3,4]
        for( let i = 0; i < arr.length; i ++){
            setTimeout(function(){
                console.log(i)
            })
        }
    } 
    close()//0,1,2,3
    

    es6区块作用域变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。

    2排序

    快排

    var arr = [1,3,6,2,8,7]
    function quickSort(arr){
        if (arr.length<=0) {return arr} ;
        let mid = arr.splice((arr.length/2),1),
        left = [],
        right = [];
        arr.forEach(function(item){
            item < mid ? left.push(item) : right.push(item)
        })
        return quick(left).concat(mid,quick(right))
    }
    console.log(qucikSort(arr))//1,2,3,6,7,8
    

    "快速排序"的思想很简单,整个排序过程只需要三步:
    (1)在数据集之中,选择一个元素作为"基准"(pivot)。
    (2)所有小于"基准"的元素,都移到"基准"的左边;所有大于"基准"的元素,都移到"基准"的右边。
    (3)对"基准"左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。

    冒泡排序

    var arr = [1,3,6,2,8,7]
    function bullSort(arr){
        var temp= [];
        for(var i = 0; i < arr.length-1; i++){
            for(var j = i+1; j < arr.length; j++){
                if(arr[i] > arr[j]){
                    var temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                }
            }
        }
        return arr
    }
    console.log(bullSort(arr))//1,2,3,6,7,8
    

    随便从数组中拿一位数和后一位比较,如果是想从小到大排序,那么就把小的那一位放到前面,大的放在后面,简单来说就是交换它们的位置,如此反复的交换位置就可以得到排序的效果。

    3js继承

    类继承

    var Father = function(){
        this.name = "xiaowang";
        this.age = 18;
    }
    Father.prototype.run = function(){
        console.log(this.name+this.age)
    }
    var Child = function(){
        
    }
    Child.prototype = new Father() 
    var child1 = new Child();
     child1.run();//xiaowang18
    

    构造函数Child通过prototype(原型)等于构造函数Father的一个实列来继承构造函数Father的所有属性和方法
    Child.prototype = new Father() = Father._proto

    构造函数继承

    //构造函数继承
    var Father = function(){
        this.name = "xiaowang";
        this.age = 18;
    };
    Father.prototype.run = function(){
        console.log(this.name+this.age)
    };
    var Child = function(){
        Father.call(this)
    };
    Child.prototype = new Father() 
    var child1 = new Child();
    // console.log(child1);
    

    构造函数Child通过改变call函数改变this指向来继承构造函数Father的所有属性和方法
    Child = this = Father

    组合式继承

    ar Father = function(){
        this.name = "xiaowang";
        this.age = 18;
    };
    Father.prototype.run = function(){
        console.log(this.name+this.age)
    };
    var Child = function(){
        Father.call(this)
    };
    var child1 = new Child();
    // console.log(child1);
    

    链接:js:面向对象编程,带你认识封装、继承和多态

    4 this,call,apply,bind

    call,apply,bind干什么的?为什么要学这个?在没有学之前,通常会有这些问题。

    var a = {
        user:"xiaowang",
        fn:function(){
            console.log(this.user);
        }
    }
    var b = a.fn;
    b(); //undefined
    

    b方法执行的this是全局window而window是没有定义user这个属性的所以最后结果是undefined。
    apply 和 call 的区别:
    apply 和 call 基本类似,他们的区别只是传入的参数不同。apply只能传入一个参数但可以是一个数组,而call可以传入多个参数

    var a = {
        user:"xiaowang",
        fn:function(){
            console.log(this.user);
        }
    }
    var b = a.fn;
    b.call(a); //xiaowang
    
    var a = {
        user:"xiaowang",
        fn:function(){
            console.log(this.user);
        }
    }
    var b = a.fn;
    b.apply(a); //xiaowang
    

    bind方法可以理解为定义了一个方法想要有效果的话必须执行该方法,即后面再加一个括号

    var a = {
        user:"xiaowang",
        fn:function(){
            console.log(this.user);
        }
    }
    var b = a.fn;
    b.bind(a)(); //xiaowang
    
    function log(){
        console.log.apply(console, arguments);
    };
    log("aa","bb")
    

    5数组一些方法

    1去重

    根据json特性不能有相同key值实现

    function unique(arr){
        var json = {};
        for(var i = 0; i < arr.length; i ++){
            if(json[arr[i]]){
                json[arr[i]]++;
            }else{
                json[arr[i]]=1;
            }
        }
    console.log(json) 
    }
    

    es6特性数组不可以有相同数字

    function unique(arr){
        console.log(...new Set(arr))
    }
    

    第一个和第二个数字对比如果相同则跳过

    function unique(arr){
        var result = [],
        i,
        j,
        len = arr.length;
        for(i = 0; i < len; i++){
            for(j = i + 1; j < len; j++){
                if(arr[i] === arr[j]){
                    j = ++i;
                }
            }
            result.push(arr[i]);
        }
      }
    

    2扁平化数组

    根据toString将数组变为用,分割的数组字符串然后再转为数字

    var flatt= function(){
        var arr = [1,2,3,[1,2,3,[1,2,3]]];
        var arrstr = arr.toString().split(",")
        var arr1 = [];
        for(var i = 0; i < arrstr.length; i ++){
            arr1.push(Number(arrstr[i]))
        }
        console.log(arr1)
     }
    

    使用数组判断方法Array.isArray判断是否为数组,递归操作数组

    var flatt= function(){
        var arr = [1,2,3,[1,2,3,[1,2,3]]];
        var res = [];
        for(var i = 0; i < arr.length; i ++){
            if(Array.isArray(arr[i])){
                res = res.concat(flatt(arr[i]))
            }else{
                res.push(arr[i])
            }
        }
        console.log(res)
     }
    

    使用数组判断方法Array.isArray判断是否为数组,递归操作数组

    var flatt= function(){
        var arr = [1,2,3,[1,2,3,[1,2,3]]];
        var res = [];
        for(var i = 0; i < arr.length; i ++){
            if(Array.isArray(arr[i])){
                res = res.concat(flatt(arr[i]))
            }else{
                res.push(arr[i])
            }
        }
        return res
     }
    

    3删除数组中指定的数字

    找到要删除数字的索引,使用数组splice方法删除

    var delArr = function(){
        var arr = [1,2,3,[1,2]];
        var res = [1,2]
        function getI(arr,res){
            for(var i = 0; i < arr.length; i ++){
                if(res.toString() == arr[i].toString()){
                    return i
                }
            }
        }
        arr.splice(getI(arr,res),1);
        return arr;
    }
    

    4一个数组中出现次数最多的数字

    循环数组使用json统计数字出现的次数,然后枚举json对比一个最大值

    var maxNum = function(arr){
        var json = {};
        for(var i = 0; i < arr.length; i ++){
            if(json[arr[i]]){
                json[arr[i]]++;
            }else{
                json[arr[i]]=1;
            }
        };
        // return json
        var maxKey = null;
        var maxVal = null;
        for(name in json){
            if(maxVal < json[name]){
                maxVal = json[name];
                maxKey = name;
            }
        }
        return "出现次数最多的数"+maxKey+"出现了"+maxVal+"次"
    };
    

    5字符串反转

    function reverse(){
        var str = "abc";
        console.log([...str])
        let strarr = [...str].reverse().join("");
        console.log(strarr)
    }
    

    6 浅拷贝深拷贝

    浅拷贝只拷贝第一层对象值

    function shallowCopy(obj){
        let newObj = {}
        for(let key in obj){
            newObj[key] = obj[key]
        }
        return newObj
    }
    

    深拷贝判断对象值是否是对象,是则递归拷贝

    function deepCopy(obj){
         let newObj = {}
         for(let key in obj){
            newObj[key] = typeof obj[key] === "object" ? deepCopy(obj[key]) : obj[key]
            
         }
         return newObj
    }
    

    深拷贝新建对象改变值不会影响到原来对象

    let obj={
        name:"xiaoming",
        age:{
            name:"xiaolv"
        }
     }
     var a = shallowCopy(obj);
     a.age.name= "xiao1"
     console.log(a)
     console.log(obj)
    

    7判断数据类型方式

    1 typeof

    typeof 是解释器内部实现,根据 ECMA-262规定的几种类型的值来返回类型名称,基本上只能判断出来使用字面量方式赋值的基本数据类型

    2 instanceof

    instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性,instanceof的局限性应该也就是不能检测基本数据类型了吧,

    3 Object.prototype.toString

    所有的数据类型都可以用 Object.prototype.toString 来检测,而且非常的精准。
    返回'[object object]'字符串

    function type(obj) {
        var toString = Object.prototype.toString;
        var map = {
            '[object Boolean]'  : 'boolean', 
            '[object Number]'   : 'number', 
            '[object String]'   : 'string', 
            '[object Function]' : 'function', 
            '[object Array]'    : 'array', 
            '[object Date]'     : 'date', 
            '[object RegExp]'   : 'regExp', 
            '[object Undefined]': 'undefined',
            '[object Null]'     : 'null', 
            '[object Object]'   : 'object'
        };
        return map[toString.call(obj)];
    }
    

    4 construtor

    constructor 属性返回对创建此对象的数组函数的引用。
    链接:数据类型检测

    8 原生事件

    return 一个实例在原型上添加方法并return this

    var navtive = function(){
        var G=function(el){
            return new G_(el);
        }
        var G_=function(el){
            this.el = document.querySelector(el);
        }
        G_.prototype.on=function(ev,callback){
            this.el.addEventListener(ev,callback,false)
            return this
        }
        G(".native").on("mouseover",function(){
            alert(1)
        }).on("mouseout",function(){
            alert(2)
        })
    }
    // navtive();
    

    相关文章

      网友评论

          本文标题:js经典题目

          本文链接:https://www.haomeiwen.com/subject/pskxlftx.html