资讯专栏INFORMATION COLUMN

前端一些需要掌握的简单知识点

n7then / 1685人阅读

摘要:快速排序由在年提出。如果定时器的时间到了,那么也会去下一个阶段关闭的回调函数,一些准备关闭的函数等的事件轮询机制也可以看成是单线程,由上往下执行,但是到了第阶段,又会返回第一阶段,死循环。

原生javaScript是中大公司挑人的核心,也是决定你未来发展高度的核心。

冒泡排序,快速排序,深度克隆,深度冻结,数组操作,本章都有。

走遍大江南北,还是原生javaScript最美

感冒给大家更新,希望大家多多点赞,谢谢!

下面是本人一些其他文章和学习的文档 , 全栈工程师一起加油!

Node.js之快速搭建微信公众号服务器

Node.js之快速搭建服务器+前后端数据库session交互

ES6教程全篇

你该拥抱的TypeScript

快速排序算法
"这应该是最简单的快速排序实现,什么是快速排序呢?"

"快速排序(Quicksort)是对冒泡排序的一种改进。
快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:
通过一趟排序将要排序的数据分割成独立的两部分,其中一
部分的所有数据都比另外一部分的所有数据都要小,然后再
按此方法对这两部分数据分别进行快速排序,整个排序过程
可以递归进行,以此达到整个数据变成有序序列。"
function quickSort(arr) {
        if (arr.length <= 1) { return arr; }
        var left = [],
            right = [],
            baseDot = Math.round(arr.length / 2)
            base = arr.splice(baseDot, 1)[0];

        for (var i = 0; i < arr.length; i++) {
            if (arr[i] < base) {
                left.push(arr[i])
            } else {
                right.push(arr[i])
            }
        }
        return quickSort(left).concat([base], quickSort(right));
    }
    let arr = [5, 3, 4, 12];
    
    const newarr = quickSort(arr);
    console.log(newarr);
    
    
    "每次递归调用,都会直到数组中只有一个数字为止,然后
    执行上下文栈出栈,返回上一个执行上下文循环递归,拼接数组"
冒泡排序算法
"什么是冒泡排序算法?"

"冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。
它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果他们的顺
序(如从大到小、首字母从A到Z)错误就把他们交换过来。走访元素的工作
是重复地进行直到没有相邻元素需要交换,也就是说该元素已经排序完成。
这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端
(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端
一样,故名“冒泡排序”。"


    bubbleSortSoul1 = (arr = []) => {
        let count = 0;
        // i为轮数(因i从0开始 即iarr[j]? 如果有这种特殊癖好 那么j就从1开始吧,然后j arr[j + 1]) {
                    let temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
        console.log(`bubbleSortSoul1排序完成用了${count}轮`);
        return arr;
    }
深度克隆

"为什么我们需要深度克隆?而且面试必问?"

"因为引用数据类型存储在堆空间中,当两个变量同时指向同一个地址时,
只要一个改变,那么另外一个也会跟着变,我们的原意是想一个改变,另
一个不变,那么就需要重新开拓一个堆空间出来,所以就有了深度克隆。"

"第一种方法(只适用于基础类型)"

const newObj = JSON.parse(JSON.stringify(oldObj));


"第二种方法,涵盖所有的类型"

const getType = (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",
        "[object Symbol]"   : "symbol"
    };
    if(obj instanceof Element) {//因为对不同标签,toString会返回对应不同标签的构造函数
        return "element";
    }
    return map[toString.call(obj)];
}

const getRegExp = re => {
  var flags = "";
  if (re.global) flags += "g";
  if (re.ignoreCase) flags += "i";
  if (re.multiline) flags += "m";
  return flags;
};

/**
* deep clone
* @param  {[type]} parent object 需要进行克隆的对象
* @return {[type]}        深克隆后的对象
*/
const deepClone = oldObj => {
  // 维护两个储存循环引用的数组
  const oldObjArr = [];
  const newObjArr = [];

  const clone = oldObj => { 
      
    let newObj, proto;

    const type = getType(oldObj);

    switch(type){
        case "boolean":
        case "number":
        case "string":
        case "null":
        case "undefined":
        case "function":{
            return oldObj;
            break;
        }
        case "symbol":{
            return Symbol(Symbol.keyFor(oldObj).toString());
            break;
        }
        case "array":{
            newObj = [];
            break;
        }
        case "regExp":{
            newObj = new RegExp(oldObj.source, getRegExp(oldObj));
            if (oldObj.lastIndex) newObj.lastIndex = oldObj.lastIndex;
            break;
        }
        case "date":{
            newObj = new Date(oldObj.getTime());            
            break;
        }
        //case "obj":
        default:{
            // 处理对象原型
            proto = Object.getPrototypeOf(oldObj);
            // 利用Object.create切断原型链
            newObj = Object.create(proto);
            break;
        }
   }

   // 处理循环引用
   const index = oldObjArr.indexOf(oldObj);
   if (index != -1) {// 如果父数组存在本对象,说明之前已经被引用过,直接返回此对象    
     return newObjArr[index];
   }

   oldObjArr.push(oldObj);
   newObjArr.push(newObj);
  /*数组和对象都可以用forin语句,虽然数组使用forin会有一个问题(具体看最下面)。
  但是这里不会影响,所以这么用 
  */
   for (let i in oldObj) {// 递归     
     newObj[i] = clone(oldObj[i]);
   }

   return newObj;
 };


 return clone(oldObj);
}

/*
测试成功
*/
function person(pname) {
    this.name = pname;
}
  
const Messi = new person("Messi");
  
function say() {
    console.log("hi");
};
  
const oldObj = {
    a: say,
    b: new Array(1),
    c: new RegExp("ab+c", "i"),
    d: Messi
  };
  
  const newObj = deepClone(oldObj);
  
  console.log(newObj.a, oldObj.a); //[Function: say] [Function: say]
  console.log(newObj.b[0], oldObj.b[0]); // undefined undefined
  console.log(newObj.c, oldObj.c); // /ab+c/i /ab+c/i
  console.log(newObj.d.constructor, oldObj.d.constructor); // [Function: person][Function: person]
  
 "所有的类型都可以被克隆,完美版"
 

判断对象是否一个数组的条件是:

Array.isArray(),这个在安卓的浏览器中兼容性一般

arr instanceof Array 这个兼容性不错,可以使用

还有就是arr. _proto_ .consturctor == Array 这个也是可以的 兼容性应该还不错

Object.prototype.tostring.call(arr) == [object Array] 这个也可以

如何提取用最原生的方法提取一个对象内部所有属性的值,并且放在不同数组中?

个人认为第一题和第二题结合起来,可以用来处理前后台交互的数据,如果格式很复杂,也可以使用这两者的模式结合,然后把他们分别提取出来进行操作。

    const obj = {
        name: "json",
        age: 1,
        friend: "梦露",
        info: {
            name: "Aron",
            age: 2,
            friend: "杰西卡",
            info: {
                name: "rose",
                age: 3,
                friend: "霉霉",
                info: {
                    name: "jerry",
                    age: 4,
                    friend: "比伯",
                    info: {
                        name: "damu",
                        age: 5,
                        friend: "XJ",
                    },
                },
            },
        }
    }
    let namearr, agearr, friendarr;
    namearr = [];
    agearr = [];
    friendarr = [];
    check(obj);
    function check(obj) {
        const items = Object.getOwnPropertyNames(obj)
        items.forEach(function (item) {
            if (Object.prototype.toString.call(obj[item]) == "[object Object]") {
                check(obj[item]);
            } else {
                if (item.toString() === "name") {
                    namearr.push(obj[item])
                } else if (item.toString() === "age") {
                    agearr.push(obj[item])
                } else if (item.toString() === "friend") {
                    friendarr.push(obj[item])
                }
            }
        })
    }
    /* 这种方法也是一样的效果  使用for in循环代替的Object.getOwnPropertyNames(obj)方法
    function check(obj) {
        for (var item in obj) {
            if (Object.prototype.toString.call(obj[item]) == "[object Object]") {
                check(obj[item]);
            } else {
                if (item == "name") {
                    namearr.push(obj[item])
                }
                else if (item == "age") {
                    agearr.push(obj[item])
                }
                else if (item == "friend") {
                    friendarr.push(obj[item])
                }
            }
        }
    }*/
    console.log(`namearr:${namearr}`)
    console.log(`agearr:${agearr}`)
    console.log(`friendarr:${friendarr}`)
请手写一个数组由小到大排序而且去重,不得使用高阶函数
    let arr = [1, 1, 2, 2, 5, 5, "a", "a", "3", "3"]
    arr = arr.sort();
    let realarr = [];
    for (let i = 0; i < arr.length; i++) { 
        if (i == 0) {
            realarr.push(arr[i])
        } else if (i !== 0 && arr[i] !== arr[i - 1]) {
            realarr.push(arr[i])
        }
    }
    console.log(realarr)

### 如何将一个对象深度冻结?

跟上面的数组面试题一样,利用了执行上下文栈,先进的后出,最先冻结最深层里面的那个属性,
再依次返回上一层继续冻结
var obj = {
       name:"王宝强",
       age:18,
       wife:{
           name:"陈羽凡",
           age:17,
           son:{
               name:"贾乃亮",
               age:48,
               girlFriend:{
                   name:"吴秀波",
                   age:50,
                   zuo:function () {
                       console.log("翻旧账")
                   },
                   foods:["棉花糖","粉色的棉花糖","各种棉花糖",{a:"a"}]
               }
           }
       }
   };



   Object.prototype.deepFreeze = function () {
       var keys = Object.getOwnPropertyNames(this);

       var that = this;
       keys.forEach(function (key) {
           var val = that[key];
           if(Object.prototype.toString.call(val) === "[object Object]" || Object.prototype.toString.call(val) === "[object Array]"){
               val.deepFreeze()
           }
       });
       return Object.freeze(this)
   }
   obj.deepFreeze()

## 请使用定时器和canvas写一个随机生成多个彩色泡




   
   
   
   Document
   



   





请自己定义一个DOM节点的R操作,以此作为queryselector在IE8以下的polifill。
(function(w){
    w.app = {};
    w.app.getElementByClassName=function(className){
        var allnode=document.getElementsByTagName("*");
        console.log(allnode)
        var arr=[];
        for(var i=0;i
请你手写一个ajax原生javaScript请求?
"由于ajax一般用于比较旧的技术,这里不适用ES6语法"

var xhr = new XMLHttpRuest();
 xhr.onreadystatechange = function () {
              if (xhr.readyState == 0) {
                  //xhr对象创建好了 初始化状态
                  console.log(0)
              }
              if (xhr.readyState == 1) {
                  //代表xhr.send方法还未调用(还未发送请求),还可以设置请求头相关信息
                  console.log(1)
              }
              if (xhr.readyState == 2) {
                  //此时send方法被调用了  响应头和首行已经回来了
                  console.log(xhr.getResponseHeader("etag"))
                  console.log(2)
              }
              if (xhr.readyState == 3) {
                  console.log(3)
              }
              if (xhr.readyState === 4 && xhr.status === 200) {
                  console.log(4)
                  console.log(xhr.responseText);
              }
          }
          xhr.open("GET", "http://localhost:3000/ajax?username=123&password=456");
          // xhr.setRequestHeader("content-type", "application/x-www-form-urlencoded");
          //  xhr.send("username=123&password=456");
          xhr.send()
      }*/
    "//上面是原生的ajax写法,下面是jQuery中的两种ajax写法"
   " 1. 原生jQuery写法 "
     $("#btn").click(function () {
          $.ajax({
              url: "http://localhost:3000/ajax",
              data: "username=jack&password=123",
              method: "POST",
              success: function (data) {
                 console.log(data)
              },
              error: function (error) {
                  console.log(error)
              }
          })
    

   "2.简写"
    
     $.post("http://localhost:3000/ajax", "username=rose&age=12", (data) => {
            console.log(data)
        })
    "//如果是get请求直接上面改成get就可以了,data是服务器响应回来的数据"
    
    
然后这边给一下服务器 Node.js的express代码 响应上面的ajax请求的
const express = require("express");
const app = express();
app.use(express.static("public"))
app.use(express.urlencoded({ extended: true }));
app.get("/ajax", (req, res) => {
    console.log(req.query)
    res.send("这是ajax的get请求")
})
app.post("/ajax", (req, res) => {
    res.send("这是ajax的post请求")
     console.log(req.body)
})
app.listen(3000, err => {
    if (!err) {
        console.log("端口监听成功");
    } else {
        console.log("端口监听失败" + err);
    }
})
如何使用原生javaScript方法提取一个多重对象的值,并且塞到不同对应的数组中?
"这里使用了递归,还有Object原型上的方法,执行上下文栈先进后出的知识。"
    const obj = {
        name: "json",
        age: 1,
        friend: "梦露",
        info: {
            name: "Aron",
            age: 2,
            friend: "杰西卡",
            info: {
                name: "rose",
                age: 3,
                friend: "霉霉",
                info: {
                    name: "jerry",
                    age: 4,
                    friend: "比伯",
                    info: {
                        name: "damu",
                        age: 5,
                        friend: "XJ",
                    },
                },
            },
        }
    }
    let namearr, agearr, friendarr;
    namearr = [];
    agearr = [];
    friendarr = [];
    check(obj);
    /*  function check(obj) {
          const items = Object.getOwnPropertyNames(obj)
          items.forEach(function (item) {
              if (Object.prototype.toString.call(obj[item]) == "[object Object]") {
                  check(obj[item]);
              } else {
                  if (item.toString() === "name") {
                      namearr.push(obj[item])
                  } else if (item.toString() === "age") {
                      agearr.push(obj[item])
                  } else if (item.toString() === "friend") {
                      friendarr.push(obj[item])
                  }
              }
          })
      }*/
    function check(obj) {
        for (var item in obj) {
            if (Object.prototype.toString.call(obj[item]) == "[object Object]") {
                check(obj[item]);
            } else {
                if (item == "name") {
                    namearr.push(obj[item])
                }
                else if (item == "age") {
                    agearr.push(obj[item])
                }
                else if (item == "friend") {
                    friendarr.push(obj[item])
                }
            }
        }
    }
    console.log(`namearr:${namearr}`)
    console.log(`namearr:${agearr}`)
    console.log(`namearr:${friendarr}`)
    

## 请手写一个jsonp和cors 解决跨域问题的代码 ?

"jsonp"
 document.getElementById("btn").onclick = function () {
   /*
     1. jsonp
       - 特点:
         1. 利用script标签天然跨域跨域的特性解决跨域的, 民间推出的
         2. 兼容性极好
    */
   //创建一个script标签
   const script = document.createElement("script");
   //设置了响应成功的回调函数
   window.jsoncallback = function (data) {
     console.log(data);
   }
   //设置script的src属性, 向指定服务器发送请求
   script.src = "http://localhost:3000/?callback=jsoncallback";
   //添加到body中生效
   document.body.appendChild(script);
 }
 
 
 ------
 
 "cors的解决方法:在Node.js的服务器代码中设置一个响应头"
   
   

app.get("/cors", (req, res) => {
 /*
   1. cors
     特点:
       - 官方推出解决跨域的方案,使用起来及其简单,只需在服务器设置一个响应头
       - 兼容性较差
  */
 //设置响应头
 res.set("access-control-allow-origin", "*");  //允许所有网址跨域
 
  
浏览器的轮询机制请简述
"1.浏览器的事件轮询机制 
浏览器中对于js依靠js引擎实现,js引擎是单线程,不像java,php这些可以是多线程,高并发。如果要说到浏览器的轮询机制,那么我们首先要说的
就是单线程的js引擎,前端的核心编程思维模式是异步编程,无论是页面效果、前后端的数据交互,都是以异步为核心,每个需要异步的场景,
往往伴随着回调函数去执行,而单线程的JS引擎是无法自身做这么多工作,还需要异步线程。

1.每当JS引擎解析代码时遇到异步代码时,交给异步线程,继续往下解析代码。
2.异步线程处理这些异步代码时,一旦他们的所对应的回调函数达到执行条件便会塞进异步队列中,等待JS引擎的轮询。
3.JS引擎会在解析完下面的所有代码后,再去轮询异步队列,从左到右,依次执行,这也是说为什么定时器的时间不准确的原因,在JS
解析代码时,如果遇到下面代码特别多的时候,那么它就没时间去轮询异步队列的代码。

浏览器中的轮询机制有一个特殊的 requestAnimationFrame(callbackname),它所对应的回调函数,是在浏览器下一次重绘重排时执行,它是一个宏任务,有待考证
,目前看只要触发重绘重排就会调用回调函数,可以避免掉帧,优化性能,减少重绘重排次数,即使一个空白页面,它也会重绘重排,所以只要运用好,
它是完全可以替代定时器,还可以使用cancelAnimationFrame(callbackname)清除。
"
Node.js中的事件轮询机制 Event loop
"Node.js的事件轮询机制外还有同步代码,微任务,
要想彻底弄懂Node的代码执行,得结合下面的微任
务一起学习。"

"1.执行已经到时间的setTimeout 和 setInterval 
2.执行延迟到一个循环迭代的i/o回调
3.系统内部的 idle prepare等
4.poll   轮询回调队列,依次取出,同步执行,与JS的异步队列执行有点相像  直到回调队列为空 或者系统奔溃了  如果回调队列没有内容,那么看
之前是否设置过setImmadiate(),如果有就去下一个阶段,如果没有,就在当前等待新的回调函数。  如果定时器的时间到了,那么也会去下一个阶段 
5. setImmediate
6.关闭的回调函数 ,一些准备关闭的函数等.

Node.js的事件轮询机制也可以看成是单线程,由上往下执行,但是到了第6阶段,又会返回第一阶段,死循环。  "
什么是微任务什么是宏任务?
"想得太多反而不好,把每个宏任务看成银行排队的老大爷,把微任务看成老大爷需要的业务,
可能他需要办存款,理财,买纪念币等,柜台人员不帮老大爷办完
他所需要的任务 -- 微任务,就不会切换到下一个老大爷 -- 宏任务, 但是编程的逻辑不
能完全抽象成现实生活,
照这种说法,只能先有老大爷才会有业务需要,
。可是在Node中,先执行的是微任务,只有微任务如果有多层,先执行最顶层,再往下依次执
行)执行完后才能去执行宏任务,微任务有两种,一种是process.nextTick()
中的函数,一种是Promise.then()中的函数,只有他们执行完后,才会去执行宏任务:setTim
eout ,setIneterval,setImmadie。(即执行完了微任务才会遵循Node.js的轮询机制去执行,
一切微任务优先)"

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/102719.html

相关文章

  • 一名【合格】前端工程师自检清单

    摘要:在他的重学前端课程中提到到现在为止,前端工程师已经成为研发体系中的重要岗位之一。大部分前端工程师的知识,其实都是来自于实践和工作中零散的学习。一基础前端工程师吃饭的家伙,深度广度一样都不能差。 开篇 前端开发是一个非常特殊的行业,它的历史实际上不是很长,但是知识之繁杂,技术迭代速度之快是其他技术所不能比拟的。 winter在他的《重学前端》课程中提到: 到现在为止,前端工程师已经成为研...

    罗志环 评论0 收藏0
  • 一名【合格】前端工程师自检清单

    摘要:在他的重学前端课程中提到到现在为止,前端工程师已经成为研发体系中的重要岗位之一。大部分前端工程师的知识,其实都是来自于实践和工作中零散的学习。一基础前端工程师吃饭的家伙,深度广度一样都不能差。开篇 前端开发是一个非常特殊的行业,它的历史实际上不是很长,但是知识之繁杂,技术迭代速度之快是其他技术所不能比拟的。 winter在他的《重学前端》课程中提到: 到现在为止,前端工程师已经成为研发体系...

    isaced 评论0 收藏0
  • 如何成为一名优秀web前端工程师(前端攻城师)?

    摘要:我从没有听到有人问如何做一名优秀甚至卓越的前端工程师。作为一个优秀的前端工程师还需要深入了解以及学会处理的这些缺陷。再者,优秀的前端工程师需要具备良好的沟通能力,因为前端工程师至少都要满足四类客户的需求。   我所遇到的前端程序员分两种:   第一种一直在问:如何学习前端?   第二种总说:前端很简单,就那么一点东西。   我从没有听到有人问:如何做一名优秀、甚至卓越的WEB前端工程师...

    Turbo 评论0 收藏0
  • 如何成为一名优秀web前端工程师(前端攻城师)?

    摘要:我从没有听到有人问如何做一名优秀甚至卓越的前端工程师。作为一个优秀的前端工程师还需要深入了解以及学会处理的这些缺陷。再者,优秀的前端工程师需要具备良好的沟通能力,因为前端工程师至少都要满足四类客户的需求。   我所遇到的前端程序员分两种:   第一种一直在问:如何学习前端?   第二种总说:前端很简单,就那么一点东西。   我从没有听到有人问:如何做一名优秀、甚至卓越的WEB前端工程师...

    rubyshen 评论0 收藏0
  • 如何成为一名优秀web前端工程师(前端攻城师)?

    摘要:我从没有听到有人问如何做一名优秀甚至卓越的前端工程师。作为一个优秀的前端工程师还需要深入了解以及学会处理的这些缺陷。再者,优秀的前端工程师需要具备良好的沟通能力,因为前端工程师至少都要满足四类客户的需求。   我所遇到的前端程序员分两种:   第一种一直在问:如何学习前端?   第二种总说:前端很简单,就那么一点东西。   我从没有听到有人问:如何做一名优秀、甚至卓越的WEB前端工程师...

    mingzhong 评论0 收藏0

发表评论

0条评论

n7then

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<