2020-题目(JavaScript)

18 篇文章 0 订阅
18 篇文章 2 订阅

题目(JavaScript)

1.this指向问题

    var length = 10

    function fn(){
      console.log(this.length)
    }
    
    let obj = {
      length : 5,
      method : function(fn){
        fn()
        arguments[0]()
      }
    }

    obj.method(fn,1) // 执行结果:10 2

2.声明提前

    function fn(a){
      console.log(a)
      var a = 2
      function a(){}
      console.log(a)
    }

    fn(1) // ƒ a(){}   2

3.局部变量和全局变量

    var f = true
    if(f===true){
      var a = 10
    }
    function fn(){
      var b = 20
      c = 30
    }
    fn()
    console.log(a) // 10
    console.log(c) // 30 未声明则强行创建全局变量b=30 
    console.log(b) // undefined

4.变量隐式声明

    // in:专门判断一个对象中,是否包含指定名称的属性
    // 一切全局对象,其实都是window对象的成员
    if('a' in window){
      var a = 10
    }
    alert(a) // 10
    console.log(a) // 10
    console.log(window.a) // 10
    console.log(window['a']) // 10

    var a1 = 10
    window.a2 = 20
    window['a3'] = 30
    let a4 = 40
    delete window.a1
    delete window.a2
    delete window.a3
    delete window.a4
    console.log(window)
    // a: 10
    // a1: 10 用var创建的全局变量无法被delete删除,所以创建对象时建议使用window.变量名;或者使用let

5.给基本类型数据添加属性不报错,但访问值时是undefined – 包装类型

    /*
    包装类型:
    专门封装原始类型,并提供对原始类型执行操作的API
    每当对原始类型的值调用方法或访问属性时,都会自动创建包装类型对象
    原理:表面上是对原始类型的变量调用方法,实际上是对自动创建的包装类型对象调用方法和访问属性,调用完毕后包装类型对象自动释放
    */
    var a = 10
    a.pro = 10
    /*
    typeof a 返回number,则:
    new Number(10).pro = 10
    随着包装类型对象释放,pro也被释放
    */
    console.log(a.pro + a) // NaN
    /*
    再次访问a.pro,再次new Number(10).pro,返回undefined
    undefined + 10 = NaN
    */

    var s = 'hello'
    s.pro = 'world'
    /*
    typeof s 返回string,则:
    new String('hello').pro = 'world'
    随着包装类型对象释放,pro也被释放
    */
    console.log(s.pro + s) // undefinedhello,原因同上
    /*
    再次访问s.pro,再次new String('hello').pro,返回undefined
    undefined + 'hello' = undefinedhello
    */

6.函数声明优于变量声明

    console.log(typeof fn) // function
    function fn(){}
    var fn = 10

7.经典利用闭包问题

使用场景:如需给一个函数绑定一个专属变量,需要用到闭包

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <!-- 实现一段脚本,使得点击对应链接alert出相应的编号 -->
  <button>1</button>
  <button>2</button>
  <button>3</button>
  <button>4</button>


  <script>
    var btns = document.getElementsByTagName('button')
    var i = 1

    for(var btn of btns){

      btn.onclick = (function(i){
        // 相当于 var i = 全局变量i传入的值1、2、3、4
        return function(){ // 利用闭包(i=1)(i=2)(i=3)(i=4)
          alert(i)
        }
      })(i++)

    }
  </script>
</body>
</html>

或者如下图所示
在这里插入图片描述

8.原型对象和继承,及事件处理函数中this的指向

    function JSClass(){
      this.m_Text = 'division element'
      this.m_Element = document.createElement('div')
      this.m_Element.innerHTML = this.m_Text
      this.m_Element.addEventListener(
        'click',this.func//.bind(this)
        /*
        事件处理函数等回调函数传递时,仅传递.后的函数对象,不会保留.前的对象
        因此,当回调函数执行时,this和原理.前的对象无关
        而是指向调用该函数的对象,即div.m_Text,也即undefined
        若要将this的指向绑定将来new出的新对象,改写为this.func.bind(this)即可,可得division element
        */
      )
    }

    JSClass.prototype.Render = function(){
      document.body.appendChild(this.m_Element)
    }

    JSClass.prototype.func = function(){
      alert(this.m_Text)
    }

    var jc = new JSClass()
    jc.Render() // 点击后弹框显示 undefined
    jc.func() // 弹框显示 division element

9.split

编写一个函数parseQueryString,把URL参数解析为一个对象

    // http://localhost:3000products?key0=0&key1=1&key2=2
    // search = location.search
    var search = '?key0=0&key1=true&key2=hello'
    search = search.slice(1)

    var strs = search.split('&')
    console.log(strs)

    var params = {}
    // 遍历每个字符串,按'='切割,第[0]个作属性名,第[1]个作属性值
    for(var str of strs){
      var arr = str.split('=')
      // params[arr[0]] = arr[1]
      params[arr[0]] = isNaN(arr[1]) ? arr[1] :Number(arr[1])
    }

    console.log(params)
    /*
    params = {
      key0:0,
      key1:1,
      key2:2,
    }
    */

10.JS数据类型

  • 基本数据类型:undefined、null、boolean、number、string、symbol
  • 引用数据类型:object、array、function

11.检查浏览器版本有哪些方式

12.JS(ES)有哪些内置对象

  • 数据封装类对象:Object、Array、Boolean、Number、String
  • 其他对象:Function、Argument、Math、Date、RgeExp、Error
  • ES6新增对象:Symbol、Map、Set、Promise、Proxy、Reflect

13.JavaScript基本规范

  • 代码缩进
  • 代码段使用{}包裹
  • 语句结束使用分号
  • 变量和函数在使用前进行声明
  • 以大写字母开头命名构造函数,全大写命名常量
  • 规范定义JSON对象,补全双引号

14.如何编写高性能JavaScript

  • 遵循严格模式:“use strict”
  • 将js脚本放在页面底部,加快渲染页面
  • 将js脚本成组打包,减少请求
  • 使用非阻塞方式下载js脚本
  • 尽量使用局部变量来保存全局变量(js代码应该包裹在一个匿名函数自调中)
  • 尽量减少使用闭包
  • 使用window对象属性方法时,省略window
  • 尽量减少对象成员嵌套
  • 缓存dom节点的访问(如在jQuery中尽量使用链式操作)
  • 避免使用eval()和Function()构造器
  • 给setTimeout() 和setInterval() 传递函数而不是字符串作为参数
  • 尽量使用直接量创建对象和数组
  • 最小化重排重绘,如新增多个平级元素时,应当先加入文档片段中,再将文档片段一次性加入dom树;新增父子元素时, 应先将所有子元素加入父元素,最后一次性加载父元素

15.DOM元素e的e.getAttribute(propName) 和 e.propName 有什么联系和区别

在这里插入图片描述

16.offsetWidth/offsetHeight,clientWidth/clientHeight,scrollWidth/scrollHeight之间的区别

  • offsetWidth/offsetHeight 返回值包含 content + padding + border,效果与 e.getBoundingClientRect()相同
  • clientWidth/clientHeight 返回值只包含 content + padding ,若有滚动条,则不包含滚动条
  • scrollWidth/scrollHeight 返回值包含 content + padding + 溢出内容的尺寸

17.浏览器的渲染过程,DOM树和渲染树的区别

浏览器的渲染过程

  • 解析HTML构建DOM树,并行请求 css / image / js
  • css文件下载完成,开始构建CSSOM(CSS树)
  • CSSOM(CSS树)构建结束后,和DOM树一起生成Render Tree(渲染树)
  • 布局(layout):计算出每个节点在屏幕中的位置
  • 显示(painting):通过显卡把页面画到屏幕上

DOM树和渲染树的区别

  • DOM树与HTML标签一一对应,包括head和隐藏元素
  • 渲染树不包含head和隐藏元素,大段文本的每一行都是独立节点,每一个节点都有对应的css属性

18.重绘和回流(重排)

  • 重绘:当渲染树中的元素外观(如颜色)发生改变,不影响布局时,产生重绘
  • 回流:当渲染树中的元素布局(如尺寸、位置、隐藏/显示状态)发生改变时,产生重绘回流
    JS获取layout属性值(如:offsetLeft、scrollTop、getComputedStyle等)也会引起回流,因为浏览器需要重新布局来计算出结果
    回流必将引起重绘,重绘不一定引起回流

19.如何最小化重排重绘

  • 需要对元素进行复杂的操作时,可以先隐藏(display:“none”),操作完成后再显示
  • 需要创建多个DOM节点时,使用DocumentFragment创建完后一次性的加入document
  • 缓存layout属性值,如:var left = elem.offsetLeft,多次使用left只产生一次回流
  • 尽量避免使用table布局(table元素一旦触发回流就会导致table里所有其他的元素回流)
  • 避免使用css表达式(expression),因为每次调用都会计算值(包含加载页面)
  • 尽量使用css属性简写,如:用border代替border-width, border-style, border-color批量修改元素样式

20.script的位置是否会影响首屏显示时间

21.对 面向对象 的理解

面向对象的三大特点是封装、继承、多态
什么是封装?为什么要封装?如何封装?
什么是继承?为什么要继承?如何继承?
什么是重写?为什么要重写?如何重写?

22.介绍JavaScript的原型、原型链,及其特点

原型:

  • JavaScript的所有对象中都包含了 ‘__proto’ 的内部属性,这个属性所对应的就是该对象的原型
  • JavaScript的函数对象,除了 ‘__proto’ 之外,还预置了prototype属性
  • 当函数对象作为构造函数创建实例时,该prototype属性值将被作为实例对象的原型 ‘__proto’

原型链:

  • 当一个对象调用的属性、方法自身不存在时,就会去自己 ‘__proto’ 关联的前辈prototype对象上去找
  • 如果没找到,就会去该prototype原型 ‘__proto’ 关联的前辈prototype去找,以此类推,知道找到属性/方法或undefined为止,由此构成了所谓的原型链
  • 这种由多级原型对象逐级继承形成的结构,就叫原型链
    原型特点:
  • JavaScript对象是通过引用来传递的,当修改原型时,与之相关的对象也会继承这一改变

23.JavaScript如何实现一个类,怎么实例化这个类

1) 构造函数法,用new关键字生成实例对象

优点:e5写法,所有浏览器都支持
缺点:用到了this和prototype,编写复杂,可读性差

2)es6语法糖class,用new关键字生成实例对象

24.JavaScript如何实现继承

25.JavaScript作用域链

  • 全局函数无法查看局部函数的内部细节,但局部函数可以查看其上层的函数细节,直至全局细节
  • 如果当前作用域没有找到属性或方法,会向上层作用域查找,直至全局函数,这种形式就是作用域链

26.什么是window对象,什么是document对象

  • window对象表示当前浏览器的窗口,是JavaScript的顶级对象。我们创建的所有对象、函数、变量都是window对象的成员;window对象的属性和方法全局范围内有效
  • document对象是HTML文档的根节点与所有其他节点(元素节点、文本节点、属性节点、注释节点)。document对象使我们可以通过脚本对HTML页面中的所有元素进行访问;document对象是window对象的一部分,可通过window.document属性对其进行访问

27.DOM的浏览器兼容性问题/IE的事件处理和W3C的事件处理有哪些区别

1)事件模型
  • DOM(3个阶段):
    ① 外向内:捕获
    ② 目标触发
    ③ 内向外:冒泡执行
    DOM事件模型

  • IE8(2个阶段):
    没有捕获阶段
    ① 目标触发
    ② 内向外:冒泡执行

2)事件绑定:
  • DOM: elem.addEventListener(‘click’, function(){}, false),第3个参数capture – 是否在捕获阶段就提前触发,默认为false,即都在冒泡阶段后触发
  • IE8: elem.attachEvent(‘onclick’, function(){})
3)移除事件:
  • DOM:elem.removeEventListener(‘click’, function(){}, false) // 绑定时写了几个参数,移除时也要写几个参数,且参数必须保持一致
  • IE8:elem.detachEvent(‘onclick’, function(){}))
4)获得事件对象的方法:
  • DOM:elem.addEventListener(‘click’, function(e){}),e指向event
  • IE8:不会自动传入事件对象e,事件对象event始终保存在一个全局变量window.event中,elem.attachEvent(‘onclick’, function(){ var e = window.event })
    // 兼容所有浏览器的写法
    e = e || window.event
5)获得目标元素
  • DOM:e.target
  • IE8:e.srcElement
	// 兼容所有浏览器的写法
    var target = e.target || e.srcElement
6)阻止冒泡:
  • DOM: e.stopProPagation()
  • IE8: e.cancelBubble = true
	// 兼容所有浏览器的写法
    if(e.cancelBubble === undefined){
      // DOM
      e.stopPropagation();
    }else{
      // IE8
      e.cancelBubble = true
    }
7)阻止默认行为:
  • DOM: e.preventDefault()
  • IE8: 事件处理函数中 return false
	// 兼容所有浏览器的写法
    if(typeof e.preventDefault === 'function'){
      // DOM
       e.preventDefault()
    }else{
      // IE8
      return false
      // 或者 e.returnValue = false
    }

28.定义一个函数,可以支持所有浏览器中的处理函数的绑定(考虑浏览器的兼容性)

function bindEvent(elem, eventName, handler){
      if(typeof elem.attachEvent === 'function'){
        // IE8
        elem.attachEvent('on'+eventName, function(){
          var e = window.event
          e.target = e.srcElement
          handler.call(this, e)
        })
      }else{
        // DOM
        elem.addEventListener(eventName, handler)
      }
    }

29.DOM0, DOM2, DOM3事件处理方式区别

30.事件的代理/委托

事件委托是指将事件绑定到目标元素的父元素上,利用冒泡机制触发该事件

优点:

  • 可以减少事件注册,节省大量内存占用
  • 可以将事件应用于动态添加的子元素上

缺点:使用不当会造成事件在不应该触发时触发

31.如何获得一个DOM元素的绝对位置

  • elem.offsetLeft 返回元素相对于其定位父级左侧的距离
  • elem.offsetTop 返回元素相对于其定位父级顶部的距离

32.区分客户区坐标,页面坐标,屏幕坐标

33.[‘1’, ‘2’, ‘3’].map(parseInt)答案是多少

    ['1','2','3'].map(parseInt) // [1, NaN, NaN]
    ['1','2','3'].map(function(elem, index, arr){})
    parseInt(e1, e2) // 第一个参数代表要处理的元素,第二个参数代表进制,故:
    parseInt('1', 0) // 1, 0为无效值
    parseInt('2', '1') // NaN 1进制不可能出现2
    parseInt('3', '2') // NaN 2进制不可能出现3

34.new操作符

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值