美文网首页
前端笔面

前端笔面

作者: hjwang1024 | 来源:发表于2020-06-02 17:33 被阅读0次

    HTML 语义化

    • 用正确的标签做正确的事情。
    • html 语义化让页面的内容结构化,结构更清晰,便于对浏览器、搜索引擎解析;
    • 即使在没有样式 CSS 情况下也以一种文档格式显示,并且是容易阅读的;
    • 搜索引擎的爬虫也依赖于 HTML 标记来确定上下文和各个关键字的权重,利于 SEO;
    • 使阅读源代码的人对网站更容易将网站分块,便于阅读维护理解。

    构造函数,new时发生了什么?

    var obj  = {}; 
    obj.__proto__ = Base.prototype;
    Base.call(obj);  
    

    1.创建一个新的对象 obj;
    2.将这个空对象的_ proto_ 成员指向了Base函数对象prototype成员对象
    3.Base函数对象的this指针替换成obj, 相当于执行了Base.call(obj);
    4.如果构造函数显示的返回一个对象,那么则这个实例为这个返回的对象。 否则返回这个新创建的对象

    instanceof原理

    判断实例对象的_ proto_ 属性与构造函数的prototype是不是用一个引用。如果不是,他会沿着对象的 _ proto _向上查找的,直到顶端Object。

    使用typeof能得到哪些类型

    1. boolean
    2. number
    3. string
    4. undefined
    5. symbol
    6. object
    7. function
    8. bigint

    实现一个类型判断函数

    1.判断null
    2.判断基础类型
    3.使用Object.prototype.toString.call(target)来判断引用类型
    注意: 一定是使用call来调用,不然是判断的Object.prototype的类型 之所以要先判断是否为基本类型是因为:虽然Object.prototype.toString.call()能判断出某值是:number/string/boolean,但是其实在包装的时候是把他们先转成了对象然后再判断类型的。 但是JS中包装类型和原始类型还是有差别的,因为对一个包装类型来说,typeof的值是object

    /**
     * 类型判断
     */
    function getType(target) {
      //先处理最特殊的Null
      if(target === null) {
        return 'null';
      }
      //判断是不是基础类型
      const typeOfT = typeof target
      if(typeOfT !== 'object') {
        return typeOfT;
      }
      //肯定是引用类型了
      const template = {
        "[object Object]": "object",
        "[object Array]" : "array",
        // 一些包装类型
        "[object String]": "object - string",
        "[object Number]": "object - number",
        "[object Boolean]": "object - boolean"
      };
      const typeStr = Object.prototype.toString.call(target);
      return template[typeStr];
    }
    

    类的声明

    // 普通写法
    function Animal() {
      this.name = 'name'
    }
    
    // ES6
    class Animal2 {
      constructor () {
        this.name = 'name';
      }
    }
    

    转Boolean

    以下都为假值,其他所有值都转为 true,包括所有对象(空对象,空数组也转为真)。
    false
    undfined
    null
    ''
    NaN
    0
    -0

    == 操作符

    对于 == 来说,如果对比双方的类型不一样的话,就会进行类型转换

    判断流程:
    1.首先会判断两者类型是否相同。相同的话就是比大小了类型不相同的话,那么就会进行类型转换会先判断是否在对比 null 和 undefined,是的话就会返回 true
    2.判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number
    1 == '1'

    1 == 1
    3.判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断
    '1' == true

    '1' == 1

    1 == 1
    4.判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断
    '1' == { a: 'b' }

    '1' == '[object Object]'
    5.两边都是对象的话,那么只要不是同一对象的不同引用,都为false
    注意,只要出现NaN,就一定是false,因为就连NaN自己都不等于NaN 对于NaN,判断的方法是使用全局函数 isNaN()

    console.log(!!(new Boolean(false))输出什么 [易混淆]

    true 布尔的包装对象 Boolean 的对象实例,对象只有在 null 与 undefined 时,才会认定为布尔的 false 值,布尔包装对象本身是个对象,对象->布尔 都是 true,所以 new Boolean(false)其实是布尔的 true

    if(new Boolean(false)){
        alert('true!!');
    }
    
    //只有使用了 valueOf 后才是真正的转换布尔值,与上面包装对象与原始资料转换说明的相同:
    !!(new Boolean(false))  //true
    (new Boolean(false)).valueOf() //false
    

    obj.toString() 和Object.prototype.toString.call(obj)

    同样是检测对象obj调用toString方法,obj.toString()的结果和Object.prototype.toString.call(obj)的结果不一样,这是为什么?

    • 这是因为toString为Object的原型方法,而Array ,function等类型作为Object的实例,都重写了toString方法。不同的对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的toString方法(function类型返回内容为函数体的字符串,Array类型返回元素组成的字符串.....),而不会去调用Object上原型toString方法(返回对象的具体类型),所以采用obj.toString()不能得到其对象类型,只能将obj转换为字符串类型;因此,在想要得到对象的具体类型时,应该调用Object上原型toString方法。
    • Object.prototype.toString
      如果是原始类型,他会将原始类型包装为引用类型,然后调用对应方法
    function dd(){}
    var toString = Object.prototype.toString;
    toString.call(dd);          //[object Function]
    toString.call(new Object);  //[object Object]
    toString.call(new Array);   //[object Array]
    toString.call(new Date);    //[object Date]
    toString.call(new String);  //[object String]
    toString.call(Math);        //[object Math]
    toString.call(undefined);   //[object Undefined]
    toString.call(null);        //[object Null]
    toString.call(123)          //[object Number]
    toString.call('abc')        //[object String]
    

    'a' + + 'b' // -> "aNaN"

    因为 + 'b' 等于 NaN,所以结果为 "aNaN",你可能也会在一些代码中看到过 + '1' 的形式来快速获取 number 类型。

    this的指向有哪几种情况?

    this代表函数调用相关联的对象,通常页称之为执行上下文。

    1. 作为函数直接调用,非严格模式下,this指向window,严格模式下,this指向undefined;
    2. 作为某对象的方法调用,this通常指向调用的对象。
    3. 使用apply、call、bind 可以绑定this的指向。
    4. 在构造函数中,this指向新创建的对象
    5. 箭头函数没有单独的this值,this在箭头函数创建时确定,它与声明所在的上下文相同。

    如果对一个函数进行多次 bind,那么上下文会是什么呢?

    let a = {}
    let fn = function () { console.log(this) }
    fn.bind().bind(a)() // => ?
    

    不管我们给函数 bind 几次,fn 中的 this 永远由第一次 bind 决定,所以结果永远是 window。

    // fn.bind().bind(a) 等于
    let fn2 = function fn1() {
      return function() {
        return fn.apply()
      }.apply(a)
    }
    fn2()
    

    JavaScript 中,调用函数有哪几种方式?

    方法调用模式 Foo.foo(arg1, arg2);
    函数调用模式 foo(arg1, arg2);
    构造器调用模式 (new Foo())(arg1, arg2);
    call/apply 调用模式 Foo.foo.call(that, arg1, arg2);
    bind 调用模式 Foo.foo.bind(that)(arg1, arg2)();

    Event Loop事件循环

    1. js解析方法时,将同步任务排队到执行栈中,异步任务排队到事件队列中。

    2. 事件队列分为:
      宏任务:setTimeout,setInterval,setImmediate,I/O,UI交互事件
      微任务:process.nextTick,Promise.then

    3. 浏览器环境中执行方法时,先将执行栈中的任务清空,再将微任务推到执行栈中并清空,之后检查是否存在宏任务,若存在则取出一个宏任务,执行完成检查是否有微任务,以此循环…

    4. Event Loop在浏览器与node环境中的区别:
      浏览器环境每次执行一个宏任务,再去检查微任务
      node会清空当前所处阶段的队列,即执行所有task,再去检查微任务

    内存泄露和优化

    什么是内存泄露?

    存泄露是指程序中已分配的堆内存由于某种原因未释放或者无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统奔溃等后果。

    常见的内存泄露的场景
    • 缓存
    • 作用域未释放(闭包)
    • 没有必要的全局变量
    • 无效的DOM引用
    • 定时器未清除
    • 事件监听为空白
    内存泄露优化
    1. 在业务不需要的用到的内部函数,可以重构到函数外,实现解除闭包。
    2. 避免创建过多的生命周期较长的对象,或者将对象分解成多个子对象。
    3. 避免过多使用闭包。
    4. 注意清除定时器和事件监听器。
    5. nodejs中使用stream或buffer来操作大文件,不会受nodejs内存限制。

    cookies,sessionStorage 和 localStorage 的区别

    • cookie 是网站为了标示用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)
    • cookie 数据始终在同源的 http 请求中携带(即使不需要),记会在浏览器和服务器间来回传递。
    • sessionStorage 和 localStorage 不会自动把数据发给服务器,仅在本地保存。
    • 存储大小:
      cookie 数据大小不能超过 4k。
      sessionStorage 和 localStorage 虽然也有存储大小的限制,但比 cookie 大得多,可以达到 5M 或更大。
    • 有效期(生命周期):
      localStorage: 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据;
      sessionStorage: 数据在当前浏览器窗口关闭后自动删除。
      cookie: 设置的 cookie 过期时间之前一直有效,即使窗口或浏览器关闭
    • 共享
      sessionStorage不能共享,localStorage在同源文档之间共享,cookie在同源且符合path规则的文档之间共享

    Post 和 Get 的区别

    • GET在浏览器回退时是无害的,而POST会再次提交
    • Get请求能缓存,Post不能
    • Post相对Get相对安全一些,因为Get请求都包含在URL中,而且会被浏览器保存记录,Post不会。但是再抓包的情况下都是一样的。
    • Post 可以通过 request body来传输比 Get 更多的数据
    • URL有长度限制,会影响 Get 请求,但是这个长度限制是浏览器规定的
    • Post 支持更多的编码类型且不对数据类型限制
    • POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)

    常见状态码

    1XX 指示信息
    • 表示请求已接收,继续处理
    2XX 成功
    • 200 OK
    • 204 No content,表示请求成功,但响应报文不含实体的主体部分
    • 205 Reset Content,表示请求成功,但响应报文不含实体的主体部分,但是与 204 响应不同在于要求请求方重置内容
    • 206 Partial Content,进行范围请求
    3XX 重定向
    • 301 永久性重定向,表示资源已被分配了新的 URL
    • 302 临时性重定向,表示资源临时被分配了新的 URL
    • 303 表示资源存在着另一个 URL,应使用 GET 方法获取资源
    • 304 未修改,重定位到浏览器。自从上次请求后,请求的网页未修改过。服务器返回此响应时,不会返回网页内容。如果网页自请求者上次请求后再也没有更改过,您应将服务器配置为返回此响应(称为 If-Modified-Since HTTP 标头)。服务器可以告诉 Googlebot 自从上次抓取后网页没有变更,进而节省带宽和开销。
    • 307 临时重定向,和302含义类似,但是期望客户端保持请求方法不变向新的地址发出请求
    4XX 客户端错误
    • 404 在服务器上没有找到请求的资源
    • 403 forbidden,表示对请求资源的访问被服务器拒绝
    • 400 请求报文存在语法错误
    • 401 表示发送的请求需要有通过 HTTP 认证的认证信息
    5XX 服务器错误
    • 500 表示服务器端在执行请求时发生了错误
    • 501 表示服务器不支持当前请求所需要的某个功能
    • 503 表明服务器暂时处于超负载或正在停机维护,无法处理请求

    相关文章

      网友评论

          本文标题:前端笔面

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