JS 烧脑面试题大赏
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS 烧脑面试题大赏相关的知识,希望对你有一定的参考价值。
参考技术A答案
2、1
解析
首先基本类型数据是按值传递的,所以执行b函数时,b的参数a接收的值为1,参数a相当于函数内部的变量,当本作用域有和上层作用域同名的变量时,无法访问到上层变量,所以函数内无论怎么修改a,都不影响上层,所以函数内部打印的a是2,外面打印的仍是1。
答案
报错
解析
给函数多个参数设置默认值实际上跟按顺序定义变量一样,所以会存在暂时性死区的问题,即前面定义的变量不能引用后面还未定义的变量,而后面的可以访问前面的。
答案
10、20
解析
答案
undefined、n: 2
解析
恕笔者不才,这道题笔者做一次错一次。
反正按照网上大部分的解释是因为.运算符优先级最高,所以会先执行a.x,此时a、b共同指向的n: 1变成了n: 1, x: undefined,然后按照连等操作从右到左执行代码,a = n: 2,显然,a现在指向了一个新对象,然后a.x = a,因为a.x最开始就执行过了,所以这里其实等价于:(n: 1, x: undefined).x = b.x = a = n: 2。
答案
[]
解析
这题比较简单,arr[10]=10,那么索引3到9位置上都是undefined,arr[3]等打印出来也确实是undefined,但是,这里其实涉及到ECMAScript版本不同对应方法行为不同的问题,ES6之前的遍历方法都会跳过数组未赋值过的位置,也就是空位,但是ES6新增的for of方法就不会跳过。
答案
Goodbye Jack
解析
答案
NaN、13、NaN、1、1[object Object]、1、[object Object]
解析
这道题考察的显然是+号的行为:
1.如果有一个操作数是字符串,那么把另一个操作数转成字符串执行连接
2.如果有一个操作数是对象,那么调用对象的valueOf方法转成原始值,如果没有该方法或调用后仍是非原始值,则调用toString方法
3.其他情况下,两个操作数都会被转成数字执行加法操作
答案
456
解析
对象有两种方法设置和引用属性,obj.name和obj[\'name\'],方括号里可以字符串、数字和变量设置是表达式等,但是最终计算出来得是一个字符串,对于上面的b和c,它们两个都是对象,所以会调用toString()方法转成字符串,对象转成字符串和数组不一样,和内容无关,结果都是[object Obejct],所以a[b]=a[c]=a[\'[object Object]\']。
答案
25、20、20、25
解析
这道题考察的是this指向问题:
1.逗号操作符会返回表达式中的最后一个值,这里为inner.func对应的函数,注意是函数本身,然后执行该函数,该函数并不是通过对象的方法调用,而是在全局环境下调用,所以this指向window,打印出来的当然是window下的out
2.这个显然是以对象的方法调用,那么this指向该对象
3.加了个括号,看起来有点迷惑人,但实际上(inner.func)和inner.func是完全相等的,所以还是作为对象的方法调用
4.赋值表达式和逗号表达式相似,都是返回的值本身,所以也相对于在全局环境下调用函数
答案
1、2、3
解析
这题考察的是变量解构赋值的问题,数组解构赋值是按位置对应的,而对象只要变量与属性同名,顺序随意。
答案
[4, 5, 3]
解析
是不是从来没有用assign方法合并过数组?assign方法可以用于处理数组,不过会把数组视为对象,比如这里会把目标数组视为是属性为0、1、2的对象,所以源数组的0、1属性的值覆盖了目标对象的值。
答案
4
解析
这题考查的是自增运算符的前缀版和后缀版,以及switch的语法,后缀版的自增运算符会在语句被求值后才发生,所以x会仍以1的值去匹配case分支,那么显然匹配到为1的分支,此时,x++生效,x变成2,再执行++x,变成3,因为没有break语句,所以会进入当前case后面的分支,所以再次++x,最终变成4。
答案
true、true
解析
2.typeof对函数使用返回\'function\',class只是es6新增的语法糖,本质上还是函数,所以两者相等
答案
true、false
解析
1.没啥好说的,typeof对数字类型返回\'number\'。
2.这题考查的是运算符优先级的问题,逻辑非!的优先级比全等===高,所以先执行!!typeof count,结果为true,然后执行true === \'number\',结果当然为false,可以点击这里查看优先级列表: 点我 [1] 。
答案
2、2
解析
答案
1
解析
这道题考察的是作用域的问题,作用域其实就是一套变量的查找规则,每个函数在执行时都会创建一个执行上下文,其中会关联一个变量对象,也就是它的作用域,上面保存着该函数能访问的所有变量,另外上下文中的代码在执行时还会创建一个作用域链,如果某个标识符在当前作用域中没有找到,会沿着外层作用域继续查找,直到最顶端的全局作用域,因为js是词法作用域,在写代码阶段就作用域就已经确定了,换句话说,是在函数定义的时候确定的,而不是执行的时候,所以a函数是在全局作用域中定义的,虽然在b函数内调用,但是它只能访问到全局的作用域而不能访问到b函数的作用域。
答案
undefined
解析
这道题考察的是this的指向问题,箭头函数执行的时候上下文是不会绑定this的,所以它里面的this取决于外层的this,这里函数执行的时候外层是全局作用域,所以this指向window,window对象下没有name属性,所以是undefined。
答案
a: b: 1
解析
这道题很简单,因为assign方法执行的是浅拷贝,所以源对象的a属性会直接覆盖目标对象的a属性。
答案
undefined、1、2
解析
答案
undefined
解析
答案
打印出arr数组本身
解析
函数作为某个对象的方法调用,this指向该对象,数组显然也是对象,只不过我们都习惯了对象引用属性的方法:obj.fn,但是实际上obj[\'fn\']引用也是可以的。
答案
1、b函数本身、b函数本身
解析
2.和第一题类似,只是b没有赋值操作,那么执行到这两行相当于都没有操作,b当然是函数。
答案
2、4、1、1、2、3、3
解析
1.执行Foo函数的静态方法,打印出2。
2.执行getName,当前getName是打印出4的那个函数。
3.执行Foo函数,修改了全局变量getName,赋值成了打印1的函数,然后返回this,因为是在全局环境下执行,所以this指向window,因为getName已经被修改了,所以打印出1。
4.因为getName没有被重新赋值,所以再执行仍然打印出1。
5.new操作符是用来调用函数的,所以new Foo.getName()相当于new (Foo.getName)(),所以new的是Foo的静态方法getName,打印出2。
6.因为点运算符(.)的优先级和new是一样高的,所以从左往右执行,相当于(new Foo()).getName(),对Foo使用new调用会返回一个新创建的对象,然后执行该对象的getName方法,该对象本身并没有该方法,所以会从Foo的原型对象上查找,找到了,所以打印出3。
7.和上题一样,点运算符(.)的优先级和new一样高,另外new是用来调用函数的,所以new new Foo().getName()相当于new ((new Foo()).getName)(),括号里面的就是上一题,所以最后找到的是Foo原型上的方法,无论是直接调用,还是通过new调用,都会执行该方法,所以打印出3。
答案
it\'s Matthew, from England
it\'s Bob, from England
解析
Object.create方法会创建一个对象,并且将该对象的__proto__属性指向传入的对象,所以p1和p2两个对象的原型对象指向了同一个对象,接着给p1添加了一个name属性,然后调用了p1的setCountry方法,p1本身是没有这个方法的,所以会沿着原型链进行查找,在它的原型上,也就是person对象上找到了这个方法,执行这个方法会给address对象的country属性设置传入的值,p1本身也是没有address属性的,但是和name属性不一样,address属性在原型对象上找到了,并且因为是个引用值,所以会成功修改它的country属性,接着对p2的操作也是一样,然后因为原型中存在引用值会在所有实例中共享,所以p1和p2它们引用的address也是同一个对象,一个实例修改了,会反映到所有实例上,所以p2的修改会覆盖p1的修改,最终country的值为England。
答案
2、3、5、4、1
解析
这道题显然考察的是事件循环的知识点。
js是一门单线程的语言,但是为了执行一些异步任务时不阻塞代码,以及避免等待期间的资源浪费,js存在事件循环的机制,单线程指的是执行js的线程,称作主线程,其他还有一些比如网络请求的线程、定时器的线程,主线程在运行时会产生执行栈,栈中的代码如果调用了异步api的话则会把事件添加到事件队列里,只要该异步任务有了结果便会把对应的回调放到【任务队列】里,当执行栈中的代码执行完毕后会去读取任务队列里的任务,放到主线程执行,当执行栈空了又会去检查,如此往复,也就是所谓的事件循环。
异步任务又分为【宏任务】(比如setTimeout、setInterval)和【微任务】(比如promise),它们分别会进入不同的队列,执行栈为空完后会优先检查微任务队列,如果有微任务的话会一次性执行完所有的微任务,然后去宏任务队列里检查,如果有则取出一个任务到主线程执行,执行完后又会去检查微任务队列,如此循环。
回到这题,首先整体代码作为一个宏任务开始执行,遇到setTimeout,相应回调会进入宏任务队列,然后是promise,promise的回调是同步代码,所以会打印出2,for循环结束后调用了resolve,所以then的回调会被放入微任务队列,然后打印出3,最后打印出5,到这里当前的执行栈就空了,那么先检查微任务队列,发现有一个任务,那么取出来放到主线程执行,打印出4,最后检查宏任务队列,把定时器的回调放入主线程执行,打印出1。
答案
1、7、6、8、2、4、9、11、3、10、5、12
阿里面试题大汇总
一、JAVASE:(6.5)
- hashCode与equals的区别联系。
- 自动拆装箱
- JVM加载过程,
- JAVA内存模型,
- Object类方法,
- Hashma
- JAVA内存模型
- 索引的实现机制(B+树),优缺点
- error/exception/runtime exception区别
- 内存泄漏如何检测
二、集合:(6.8)
- concurrenthashmap 详细介绍
- HashMap实现原理 详细介绍
- Map的Key要求 不为空
- HashMap,put和get同时操作
- treemap实现 TreeMap实现原理 红黑树
- JDK1.8 HashMap改动(引入红黑树) ?重新认识JDK1.8 中不一样的HashMap
- List和set区别 ??java 常用集合list与Set、Map区别及适用场景总结
- linklist和arraylist区别,应用场景 ?Vector,ArrayList,LinkedList的区别与适用场景
- 红黑树
- 介绍一下Hashmap的原理
- 介绍一下红黑树
- Arraylist的原理
- 哈希如何解决冲突
三、线程:(6.10)
-
1. JAVA多线程实现
2. JAVA线程和进程区别
3. 线程有几种状态,怎么互相转化
4. 启动线程方式
5. 线程同步,并发操作怎么控制
6. lock和synchronized,
7. 线程池有几种,干什么用。
8. 线程池的使用时的注意事项
四、框架:(6.13)
- 描述struts的工作流程
- 对Spring的理解,项目中都用什么?
- Spring中autowire和resourse关键字的区别
- SpringMVC和Struts比较,为什么要用spring有什么优点
- Spring MVC底层实现
- Spring IOC Spring AOP是干嘛的
- 事务的ACID
- 事务隔离级别
五、数据结构:(6.12)
- 数组和链表在内存中表型形式
- 常见的排序算法它的时间复杂度和空间复杂度?
- 堆排序的具体实现?
- 排序算法
- 平衡二叉树
- 红黑树
- 介绍堆和栈
- 介绍一下红黑树
六、计算机网络:(6.14)
- HTTP状态吗
- http缓存
- http 302 https具体数据传输流程
- HTTP/HTTPS过程
- 由http升级为https需要哪些操作
- http 2 了解过吗
- OSI 7层模型
- TCP三次握手
- TCP连接断开过程,为什么要三次握手
- TCP和UDP的区别?
- TCP保证可靠性,
- DNS解析
- 三次握手,
- 超时重传
- 拥塞控制,
- 滑动窗口协议
七、设计模式:(6.15)
- 抽象工厂和工厂方法模式的区别
- 工厂模式的思想
八、其他:(6.20)
- 项目
- 自我介绍
- 还有什么问题?我就问了我哪些地方还需要学习!
- sendRedirect, foward区别
- Post和get区别
- Session,Cookie区别
- Redis的持久化?
- JVM的内存区域,垃圾回收,GC算法?
- ClassLoader?类加载过程对应的内存区域的变化?
- 聚簇索引和非聚簇索引(出现次数少)
- 数据库:隔离级别,四大特性,
- jam参数,gc参数,
- 序列化级别有什么优缺点
- linux查看日志文件
- 你了解过新版本的java吗
以上是关于JS 烧脑面试题大赏的主要内容,如果未能解决你的问题,请参考以下文章