Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

代码相关面试题合集 #40

Open
liangbus opened this issue Apr 15, 2020 · 10 comments
Open

代码相关面试题合集 #40

liangbus opened this issue Apr 15, 2020 · 10 comments
Labels

Comments

@liangbus
Copy link
Owner

liangbus commented Apr 15, 2020

1. 创建一个如图类似的开关切换按钮,hover 时触发,并符合以下条件

  1. 仅使用一个元素
  2. 开关切换时,带有过渡动画
  3. 宽度不定,resize 时能够自适应宽度,高度自定

image
image

这道题看上去,并不是很难,但是实际上考察样式方面的知识面特别广,实用性也很高,下面看看我的答案
.html

<div class="switch-btn"></div>

.css

.switch-btn{
  width: 100%;
  height: 100px;
  position: relative;
  background-color: grey;
}
.switch-btn::after{
  content: ' ';
  position: absolute;
  top: 5px;
  left: 5px;
  width: 50%;
  height: 90px;
  transition: all .3s linear;
  transform: translateX(0px);
  background-color: #fff;
}
.switch-btn:hover {
  background-color: green;
}
.switch-btn:hover::after{
  content: ' ';
  position: absolute;
  top: 5px;
  left: 5px;
  width: 50%;
  height: 90px;
  transition: all .3s linear;
  transform: translateX(calc(100% - 10px));
  background-color: #fff;
}

codepen demo

@liangbus
Copy link
Owner Author

liangbus commented Apr 15, 2020

2. 闭包相关,求 console.log() 输出

function fun(n, k) {
    console.log(k)
        return {
            fun:function(m){
                return fun(m,n);
            }
    };
}
var a = fun(0); // k -> undefined a : {fun : function(){}}
a.fun(1);
a.fun(2); 
a.fun(3);

var b = fun(0).fun(1).fun(2).fun(3);

分析

首先是声明一个 fun 函数,该函数返回一个对象,对象里面有一个属性,也叫 fun,其值是一个函数,其函数返回的是外层 fun 函数执行的结果(有点绕,当时就是给绕晕了 >_<)

var a = fun(0) 执行了一次 fun 函数,传了一个 0 (对应形参为 m)作为参数, 此时 console.log(k) 打印出来当然是 undefined 这里应该都没什么大问题,紧接着就是返回一个对象赋值给 a

a = {
    fun:function(m){
        return fun(m,n);
    }
}

a.fun(1); 传入一个参数 m,执行fun(m,n) ,m 为刚刚传入的 1,n 为之前第一次执行 fun 函数时传入的 0 (因为 n 被返回出去的函数作为参数引用,因此会常驻内存当中),因此这里再次打印值为 0,后续两个表达式同理,因为 a 并没有改变,n 值也没有改变,故均输出 0

a.fun(1); // 0
a.fun(2);  // 0
a.fun(3); // 0

然后再来看下最后一个链接调用的表达式

首次执行 fun(0) 打印 undefined 这个应该没有太大疑问

紧接着其链式执行 .fun(1) ,这时先来看下 fun(0) 的返回结果

{
    fun:function(m){
        return fun(m,n);
    }
}

这时跟上面执行 a.fun(0) 时是一样的,读取的 n 依然是之前 fun(0) 传入的 0,因此 k 打印为 0,但是这里返回给下一步链式调用的对象已经变了,是一个全新的对象,因此下一次链式调用时,返回的 fun(m, n) n 就是上一次传入的 m 值, 这就与上面 a.fun(0), a.fun(1) 不一样,这里 a 的对象一直是没有变的,因此此处输出值为

var b = fun(0).fun(1).fun(2).fun(3);
// undefined
// 0
// 1
// 2

@liangbus
Copy link
Owner Author

liangbus commented Apr 15, 2020

3. 闭包,求以下 console.log() 输出

var result = []
var a = 10
function foo(a){
    var i = 0;
    for(; i < 3; i++){
        result[i] = function() {
            a += i * a
            console.log(a)
        }
    }
}
foo(1)
result[0]()
result[1]()
result[2]()

这也算是一道经典的闭包相关的题目了。

@liangbus
Copy link
Owner Author

liangbus commented Apr 15, 2020

4. 求以下输出

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

主要考察变量提升,函数声明相关知识点

答案:

// function a() {}
// 2

函数提升优先级比变量提升要高,且不会被变量声明覆盖,但是会被变量赋值覆盖。(我猜测应该是声明还没有真正改变其变量的指向)


var length = 10
function foo() {
    console.log(this.length)
}
var obj = {
    length: 5,
    fn: function(f) {
        f()
        arguments[0]()
    }
}
obj.fn(foo, 1)

答案

// 10
// 2

调用 obj 对象下的一个函数属性 fn,fn 里面调用了传入的参数 f,也就是 foo,执行 f() 时,前面并没有调用的对象,因此 this 的指向仍然是全局,所以这里打印的是全局的 length 值
而 arguments0 同样是执行传入的对象,但是这里的调用方法已经改变了,是通过一个类数组对象来调用的,因此 this 正是指向该对象,而 this.length 即为该方法参数的长度

举例:

var length = 10
function foo() {
    console.log(this.length)
}
var arr = [foo, 4,5,6]
arr[0]() // 4

var f = true
if(f === true){
    var a = 2
}
function foo(){
    var b = 12
    c = 16
}
foo()

console.log(a)
console.log(b)
console.log(c)

答案:

// 2
// Error
// 16 ( 理论上该条语句不执行)

@liangbus
Copy link
Owner Author

liangbus commented Apr 17, 2020

5. 如何用css画一个滚动球体?

这是一个来回滚动的球体

<!-- html -->
<div class="ball">
  @
</div>
/** css **/
.ball{
  width: 200px;
  height: 200px;
  border-radius: 50%;
  color: #fff;
  font-size: 32px;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: lightgrey;
  animation: roll 3s linear infinite;
}

@keyframes roll {
  0% {
    transform: translate(0, 0) rotate(0deg)
  }
  50% {
    transform: translate(500px, 0) rotate(360deg)
  }
  100% {
    transform: translate(0, 0) rotate(0deg)
  }
}

@liangbus
Copy link
Owner Author

liangbus commented Apr 18, 2020

6. 针对以下代码,写一段 JS,使其点击输出相应的序号,比如点击第三个 alert(3)

<ul>
  <li>haha</li>
  <li>Yoyo</li>
  <li>Wowowowo</li>
  <li>Win~!</li>
</ul>

注意不能额外增加 dom 属性,比如 data-index

答案:

var list = document.getElementsByTagName('li')
  Array.from(list).forEach((item, i) => {
    item.addEventListener('click', function(){
      alert(i)
    })
  })

通过 getElementsByTagName 获得是类数组对象,因此需要一层转换,然后再对其遍历,对每一个 li 进行监听

@liangbus
Copy link
Owner Author

liangbus commented Apr 18, 2020

7. 原型链相关

7.1 原型链的终点是 ?

Object.prototype.__proto__ === null // true

7.2 Object.proto 指向?

Object.__proto__ === Function.prototype // true

image

7.3 如何创建一个不可继承的对象

开始回答的是箭头函数,然后面试官说不是他想要的答案,后来查了一下,应该是通过

Object.create(null)

来创建吧。

@liangbus
Copy link
Owner Author

liangbus commented Apr 19, 2020

8. 求以下输出

var foo = 10;
(function foo() {
    foo = 123;
    console.log(foo)
})()

答案

ƒ foo() {
    foo = 123;
    console.log(foo)
}

解释:
在非匿名 IIFE (Immediately Invoked Function Expression 立即调用的函数表达式) 中其绑定的变量相当于是绑定在 const 上,在 strict 模式下会报错,非 strict 模式下静默失败。

var foo = 10;
(function foo() {
    'use strict';
    foo = 123;
    console.log(foo)
})()

VM9289:4 Uncaught TypeError: Assignment to constant variable.

第 33 题:下面的代码打印什么内容,为什么?

@liangbus
Copy link
Owner Author

liangbus commented Apr 19, 2020

9. 问输出,为什么?

var a = {n: 1};
var b = a;
a.x = a = {n: 2};

console.log(a.x) 	
console.log(b.x)

答案:

undefined
{n: 2}

解释:
这里主要考察赋值语句的运算符优先级问题,.运算符的优先级比等号要高,当执行赋值语句时,等号左边有 . 运算符,因为会先创建对应的属性,此时 a 存的指针仍指向的是 {n: 1} 堆的地址,因此这里会首先变为 {n: 1, x: undefined},执行 = 右边语句,重置了 a 的指针,指向了新的 {n:2} 的堆,并返回其指针继续赋值给原本 a.x 指向的内容,但由于原来 b 是指向这个堆的地址的,所以 b.x 为 {n:2}

@liangbus
Copy link
Owner Author

liangbus commented Apr 26, 2020

10. 词法作用域和动态作用域

var value = 1;

function foo() {
    console.log(value);
}

function bar() {
    var value = 2;
    foo();
}

bar();

// console.log 结果是 ???

答案是 1

详见:JavaScript深入之词法作用域和动态作用域

@liangbus
Copy link
Owner Author

11. 如何交换两个数值类型变量的值,不使用额外空间

  1. 直接 ES6 方法,此方法不仅适用于数字类型
[a, b] = [b, a]
  1. 数值类型,可以通过简单计算来处理,该方法仅适用于数值类型,因为是通过运算来实现

示例:

var a = 3, b = 5
a = a+b // 求和
b = a - b // 先重新赋值给 b 
a = a - b // 再重新赋值给 a

还可以利用异或运算的特性

  • 相同的两个数异或结果为0
  • 任何数与0异或结果还是其自身
  • 异或运算满足交换律和结合律
var a = 3, b = 5
a = a^b
b = a^b
a = a^b

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant