2019年9月前端面试汇总

2019-09-14  本文已影响0人  Jsonzhang

1. flex实现骰子5点布局(答案不唯一)

简单的思路:
1.flex布局横向排列,flex-flow:wrap 可以折行
2.通过给第一个点设置右边距把第二个点顶到最右侧
3.通过给中间点设置左右边距居中
4.给第4个点设置右边距把第5个点顶到右边
5.容器设置align-content:space-between; 上下位置调整

         <style>
            .shaizi {
                width: 100px;
                height: 100px;
                display: flex;
                flex-flow: row wrap;
                background: black;
                padding: 15px;
                border-radius: 10px;
                align-content: space-between;
            }

            .item {
                width: 20px;
                height: 20px;
                background: white;
                border-radius: 100%;
                display: inline-block;
                margin-right: 60px;
            }

            .no-margin {
                margin-right: 0;
            }

            .center {
                margin: 0 40px;
            }
        </style>
        <div class="shaizi">
            <div class="item"></div>
            <div class="item no-margin"></div>
            <div class="item center"></div>
            <div class="item"></div>
            <div class="item no-margin"></div>
        </div>

效果图:


image.png

2. 说下js中继承

//方式一 构造函数继承
//缺点:只实现部分继承,原型中的属性和方法没有继承过来
//优点:在初始化子类时,可以给父类构造传递参数
function Parent(name){
    this.name=name;
}
//Parent.prototype.say = function(){
   // console.log("hello");
//}
function Child(name){
    Parent.call(this,name);
}

var a = new Child("zsl");
console.log(a.name); //zsl

//方式二 原型链继承
//缺点 1. 是改变对象的引用属性,其他对象也跟着一起改变;
//缺点 2. 是在创建子类的实例中不能向父类构造传递参数;
function Parent(){
    this.name="zhang";
    this.arr=[1,2,3];
}
function Child(age){
    this.age = age;
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;
var a = new Child(18);
var b = new Child(18);
a.arr.push(4);
console.log(a.arr); //[1,2,3,4]
console.log(b.arr); //[1,2,3,4]

//方式三 组合继承
//优点:避免了原型链继承和构造函数继承的缺点
//缺点:创建对象时会执行2次父类的构造方法
function Parent(){
    this.name="zhang";
    this.arr=[1,2,3];
}
function Child(age){
    Parent.call(this);
    this.age = age;
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;

var a = new Child(18);
var b = new Child(18);
a.arr.push(4);
console.log(a.arr); //[1,2,3]
console.log(b.arr); //[1,2,3,4]

//方式四 寄生组合式继承(最优方式)
//优点:避免了实例化对象,执行2次父类构造
function object(o){
  function F(){}
  F.prototype = o;
  return new F();
}

function extend(child,parent){
    var copyObj = object(parent.prototype);
    copyObj.constructor = child;
    child.prototype = copyObj;
}
function Parent(){
    this.name="zhang";
    this.arr=[1,2,3];
}
function Child(age){
    Parent.call(this);
    this.age = age;
}
extend(Child,Parent);

3. 以下代码运行的结果是输出()

var a=b=1;
(function(){
  var a=b=2;
})();
console.log(a,b);
// 解析
// 赋值是从右到左,所以var a=b=2;相当于 b=2;var a=b; 
// b没有var在非严格模式默认是全局变量,a有var修饰是局部变量
// console是在全局环境中,只能访问到全局变量,所以结果是a=1 b=2

4. 运行的结果在控制台输出什么?

if([] instanceof Object){
    console.log(typeof null);
}else{
    console.log(typeof undefined);
}
// 输出 object

javascript的数据类型有:
string 、number 、boolean、object、undefined (null也是object类型)
这里注意:
typeof undefined --> undefined
typeof null --> object

5. 以下程序输出什么?

function say(word){
    let word = "hello";
    console.log(word);
}
say("hi lili");
//报错 Uncaught SyntaxError: Identifier 'word' has already been declared

6.请选择正确的输出()

for(var i=0;i<5;i++){
    setTimeout(function(){
         console.log(i);
    },0);
}
// 5 5 5 5 5 
//分析这个问题前我们先看下这段代码
<script>
setTimeout(
    console.log("11");
,0);
console.log("22");
</script>
//正常输入 0 1 2 3 4
for(var i=0;i<5;i++){
    (function(i){
        setTimeout(function(){
          console.log(i);
        },0);
    })(i);
}

for(let i=0;i<5;i++){
  setTimeout(function(){
    console.log(i);
  },0);
}

你会发现虽然setTimeout在前面立即执行,但输入的结果仍然是:22 11
那么为什么会先输出22呢?
因为定时器都会被放在一个队列的数据结构中(先进先出)
只有上下文的可执行代码都执行完毕了,才会执行队列中的定时器。

这样我们就知道了,上面for循环中,先循环完5次后(这时i已经为5),才会执行定时器的代码。所以输出5个5。

7. 怎样快速去判断一个数据类型

我们熟悉的有2中方法:typeofinstanceof
这俩种方法不够快速,因为你需要不断试,才能最终确定什么类型。下面这种方法最快速:
Object.prototype.toString.call()
比如:

let o = {name:"zhang"};
let arr = [1,2,3];
let type1 = Object.prototype.toString.call(o);
let type2 = Object.prototype.toString.call(arr);
console.log(type1);
console.log(type2);
//[Object Object]
//[Object Array]

8. Vue 双向绑定原理

参考:https://juejin.im/entry/5923973da22b9d005893805a

9. 问输出结果是啥

123 instanceof Number  //false
new Number(123)  instanceof Number  //true
Number(123) instanceof Number  //false
//instanceof 只能判断对象、数组等的对象类型,不能判断基本数据类型

10. js实现二分法查找,并说出时间复杂度

//二分查找数组必须有序
function search(key,arr){
  let start=0, end=arr.length-1;
  while(start<=end){
    let mid = (start+end)/2;
    if(key<arr[mid]){
        end = mid-1;
    }else if(key>arr[mid]){
        start = mid+1;
    }else{
        return mid;
    }
  }
  return -1;
}

这里说下时间复杂度空间复杂度的概念和算法:
时间复杂度:方法运行时占用的时间
空间复杂度:方法运行时占用的内存

常用的时间复杂度记法为大O记法:T(n) = O( f(n) )
f(n) 是一个函数,表示随着问题规模n的增大,执行时间的增长率。

O(n):

比如求1到n之间数的和:

let sum=0;
for(let i=1;i<=n;i++){
    sum+=i;
}

显然循环内语句执行了n了,也就说这个方法的运行次数和问题规模n成正比,n大运行时间长,n小运行时间短。所以这个方法的时间复杂度为O(n)

O(1)

那么还有一种算法,求1到n之间数的和:

1+2+3+...(n-2)+(n-1)+n
//收尾相加
n/2(n+1)

这种方法也问题规模n没有关系,无论n是多少,只需要执行n/2(n+1)这一句代码就能得出结果,所以这个算法问题规模没有关系的,我们都就说他的时间复杂度为O(1)

O(n²)

for(let i=0;i<n;i++){
    for(let j=0;j<n;j++){
        //时间复杂度为O(1)的程序
    }
}

到这里需要说下推导大O阶的定律:

时间复杂度.jpg

到这里我们出一个考察题,看看掌握的怎么样:

for(let i=0;i<n;i++){
    for(let j=i;j<n;j++){
        //时间复杂度O(1)的程序
    }
}

里面for循环一次执行次数的顺序是:
n+(n-1)+(n-2)+....+2+1
也就是n/2(n+1),取高阶为n²/2,去除相乘的常数后就是n²,
所以这个方法的时间复杂度也是O(n²)

那接下来我们回过头看看二分法查找的时间复杂度:
其实主要看while循环的次数,比如数组长度n,一次后是n/2,while执行2次后剩的遍历区间长度就是n/2²,假设x次后找到,就是n/2ˣ >=1 ,即令 n/2ˣ =1,x= log₂n,所以二分法的时间复杂度是O(logn)。

11. 输出的顺序

setTimeout(
  function(){
      console.log("11");
  }
);

console.log("22");

Promise.resolve().then(function(){
    console.log("33");
});
// 22  33 11

注意:
Promise.resolve()返回一个Promise新的实例,这个方法中的参数有4中类型:thenable,promise对象,不具有then方法的对象或者不是对象,空参数。
立即resolve的promise对象是在本轮事件结束时执行,而setTimeout是在下一轮事件开始时执行

12. 深拷贝浅拷贝的区别,并分别用js实现

let obj = {
    name:"zhang",
    age:18,
    score:[88,80,90]
}

浅拷贝:拷贝上面obj对象,会重新生成一个一样对象,但是浅拷贝只能拷贝表层数据,不能拷贝对象的属性是对象或数组的。也就是说新对象的score属性,指向的还是原来对象score属性数组的地址。所以修改浅拷贝的对象可能会影响原来的对象。
深拷贝:完全的复制一份,生成的新对象和原来的对象互不影响。

//浅拷贝
function shallowCopy(obj){
    let c = {};
    for(let i in obj){
        c[i] = obj[i];
    }
    return c;
}
//深拷贝(递归调用)
function deepCopy(obj,c){
    let c = c || {};
    for(let i in obj){
        if(typeof obj[i] ==="object "){
            c[i] = (obj[i]===Array)?[]:{};
            deepCopy(obj[i],c[i]);
        }else{
            c[i] = obj[i];
        }
    }
    return c;
}

13. flex实现下面的布局

image.png
<style>
        .parent {
            display: flex;
            width: 300px;
            height: 200px;
            border: 1px solid green;
            justify-content: space-between;
        }

        .size {
            width: 50px;
            height: 50px;
            background: red;
        }

        .two {
            align-self: center;
        }

        .three {
            align-self: flex-end;
        }
</style>

<div class="parent">
    <div class="size"></div>
    <div class="two size"></div>
    <div class="three size"></div>
</div>

14. 获取页面元素宽高和位置

<div id="div"></div>
var node = document.getElementById("div");

//只能获取行内样式的宽高,并且无论标准还是ie盒模型,只取height属性的值
var h = node.style.height; 

//只使用于ie浏览器
var h = node.currentStyle.height; 

//都使用 但也是只取height值
var h = window.getComputedStyle(node).height;

// content+padding
var h = node.clientHeight;

// content + padding +border
var h = node.offsetHeight;

// content + padding + border
var h = node.getBoundingClientRect().height;

//获取位置就用
node.getBoundingClientRect().left
node.getBoundingClientRect().top
node.getBoundingClientRect().bottom
node.getBoundingClientRect().right
//注意:这些值是从boder开始算起的

15. 下面代码输出什么(原型链知识)

Function.prototype.a = 'a';
Object.prototype.b = 'b';
function Person(){};
var p = new Person();
console.log('p.a: '+ p.a); // p.a: undefined
console.log('p.b: '+ p.b); // p.b: b


//Object.prototype.aa = "aa";
Function.prototype.aa = "bb";
function fn() {}
console.log("zhang=" + fn.aa);  //bb

Object.prototype.aa = "aa";
//Function.prototype.aa = "bb";
function fn() {}
console.log("zhang=" + fn.aa);  //aa

Object.prototype.aa = "aa";
Function.prototype.aa = "bb";
function fn() {}
console.log("zhang=" + fn.aa);  //bb

16. 什么是闭包,手写一个闭包,说其作用

http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html

闭包是指有权访问另一个函数作用域中的变量的函数。

function closure(){
  var temp = 'zhang';
  function inner(){
    console.log(temp);
  }
  return inner;
}

作用:可以实现在函数外部访问函数内部变量

17.Dom0级事件和Dom2级事件的区别,以及Dom事件和IE事件的区别

Dom0级事件有俩种绑定方式:

<div id="div" onclick="down()">点我</div>
或者
var div = document.getElementById("div");
div.onclick = function(){
  //处理
}
//删除事件
div.onclick =null;

Dom2级事件的绑定方式:

div.addEventListener('click',function(){
    //处理
},false);
//删除事件
//匿名函数的方式无效
div.removeEventListener('click',function(){
  //处理
},false);
//这种方式有效
div.removeEventListener('click',handler,false);
var handler = function(){
  //处理事件
}

Dom0和Dom2最主要区别:给一个元素注册同一类的多个Dom0级事件,会覆盖前面的事件,只有最后注册的有效。而同样注册多个Dom2级事件会都有效,并按注册顺序执行。
Dom0和Dom2可以同时注册到一个元素,执行顺序按注册顺序。

Dom事件和IE事件的区别:Dom事件流的顺序是先捕获再冒泡,而IE事件只有冒泡,没有捕获。
注册事件的方式也不同:

// 注意事件类型onclick不是click
div.attachEvent('onclick',function(){
  //处理事件
});

//解除事件绑定
div.detachEvent('onclick',function(){
});

注意:IE事件和Dom2级事件一样,可以给一个元素注册多个同类型的事件,但是Dom2执行顺序是按注册顺序,而IE的执行顺序和注册顺序相反。

div.attachEvent('onclick',function(){
    console.log("ie事件1");
});
div.attachEvent('onclick',function(){
    console.log("ie事件2");
});
//ie事件2
//ie事件1

注意:Dom事件执行的作用域是其所属元素的作用域,而IE事件执行的作用域是全局作用域。

div.addEventListener('click',function(){
    //这里this是div所属作用域环境
},false);

div.attachEvent('onclick',function(){
    //这里this是全局作用域,即window环境
    console.log(this==window); //true
});

18. Vue父子组件和兄弟组件之间通信

https://segmentfault.com/a/1190000020053344?from=groupmessage&isappinstalled=0

19.html自上向下加载遇到<script>标签会怎样?

<script src="a.js"></script>

普通script加载流程:

script标签加上deferasync属性后,script标签不会阻塞document的解析,这时所有带deferasyncscript标签都会并行下载。

defer

<script src="a.js"></script>
<script src="b.js"></script>

async

<script src="a.js"></script>
<script src="b.js"></script>

20.@import 和 link引入外部样式有什么区别?

首先,样式有三种方式:行内样式内联样式外联样式
他们的权重是:行内样式>内联样式>外联样式

<link rel="stylesheet" type="text/css" href="./a.css">
<style type="text/css">
    @import url(b.css);
    .div{
        width:100px;
        height:100px;
        background:red;
    }
</style>
@import url(a.css) all;
@import url(b.css) screen;
@import url(c.css) projection,print;

21. CSS选择器权限问题

!important > 行内样式(1000) > id(100) > 类(10) > 标签(1) >通配符 *(0)

<style>
    .div{
        background:red !important;
    }
</style>

<div style="background:blue"></div>
//显示红色

22.下面代码输出什么

try{
  console.log(1);
  setTimeout(()=>{
    console.log(2);
    throw new Error(3);
  },0);
}catch(e){
  console.log(e);
}
// 1 2
// Uncaught error 3

try catch是同步代码,同步代码执行完毕输出1。然后执行异步代码,输出2,然后抛出异常,由于try catch已经执行完,所以不能捕获到异常。

23.求俩个数组的交集

//ES6 写法 时间复杂度O(n²)
function insertSection(arr1, arr2) {
   var a = new Set(arr1);
   var b = new Set(arr2);
   return Array.from(a).filter(x => b.has(x));
}

如果时间复杂度为O(n),怎么写?
注意:我们解决这类问题的一个思路是,将时间复杂多为On的n次方,拆为n个复杂度为O(n)的算法,再让这些算法串行执行。

//时间复杂度 O(n)
function insertSection(arr1,arr2){
  //去重
  var a = new Set(arr1);
  var b = new Set(arr2);
  //合并
  var c = [...a,...b];
  //排序 这里是一个O(n)
  var d = c.sort();
  var e = [];
  var temp;
  for(let i=0;i<d.length-1;i++){
    if(d[i]==d[i+1] && d[i]!=temp){
        e.push(d[i]);
        temp = d[i];
    }
  }
  return e;
}

24."abc efg".replace(),输入表达式,使得到的结果为"efg abc"

先来了解下String.prototype.replace(参数1,参数2)这个api
str.replace( regexp|substr, newSubStr|function )
这题我们用正则在解,所以先了解正则的几个预定义模式:
^ 表示开头 $表示结尾 ()表示一组
\w : 匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_]
\s : 匹配空格(包括换行符、制表符、空格符等,相当于[ \t\r\n\v\f]
$n : 匹配成功的第n组内容,n是从1开始的自然数。

var reg = /(\w+)\s(\w+)/;
"abc efg".replace(reg,'$2 $1');
//efg abc

25. for、for...of、for...in、forEach、map、filter、every、some、reduce

var arr = [3,5,8];
arr.forEach(function(item,index){
  console.log(item);
});
// 3 5 8
for(let i in arr){
  console.log(arr[i]); //遍历数组索引
}
//3 5 8

var obj = {name:'zhang',age:18};
for(let i in obj){
  console.log(obj[i]); //遍历对象属性
}
//zhang 18

有一点需要注意,用for...in遍历时,原型链上的所有属性都会被遍历,比如:

Array.prototype.other = [10,11];
for(let i in arr){
  console.log(arr[i]);
}
//3 5 8 [10,11]

Object.prototype.a = { sex: "man" };
var b = { name: "zhang", age: 18 };
for (let i in b) {
    console.log(b[i]);
}
//zhang 18 {sex:'man'}

那么我不想遍历原型链上的属性,怎么办呢?
hasOwnProperty:只有实例的属性可以遍历,原型上的属性不能遍历到。

Array.prototype.other = [10,11];
for(let i in arr){
  if(arr.hasOwnProperty(i)){
    console.log(arr[i]);
  }
}
//3 5 8
//遍历数组
for(let i of arr){
  console.log(i);
}
//3 5 8

//遍历字符串
var str = "zhang";
for (let i of str) {
   console.log(i);
}
//z h a n g

//遍历Map

//遍历Set

//遍历Dom集合

//遍历arguments
var b = arr.map(x=>{
  return x*2;
});
console.log(b);
//[6,10,16]
var arr = [3,5,8,10];
var b = arr.filter(x=>{
    return x>5;
});
console.log(b);
//[8,10]
var arr =[3,5,8];
var result = arr.every(x=>{
  return x>2;
});
//true
var result = arr.every(x=>{
  return x>5;
});
//false
var arr = [3,5,8];
var result = arr.some(x=>{
  return x>5;
});
//true

var result = arr.some(x=>{
  return x>12;
});
//false
var arr = [3,5,8];
var b = arr.reduce(function(sum,item){
  return sum+item;
},0); //初始值为0
console.log(b);
//16 

var b = arr.reduce(function(sum,item){
  return sum+item;
},2); //初始值为2
console.log(b);
//18

26:for...in、Object.keys()、Object.getOwnPropertyNames()的区别

var parent = Object.create(Object.prototype, {
    a: {
        value: 1,
        writable: true,
        enumerable: true,
        configurable: true            
    }
});

var child = Object.create(parent, {
    b: {
        value: 2,
        writable: true,
        enumerable: true,
        configurable: true
    },
    c: {
        value: 3,
        writable: true,
        enumerable: false,
        configurable: true
    }
});

child继承parent,child有俩个属性,b和c,不是可枚举的,c不可枚举的。
现在我们用遍历的方式打印child的属性:

//for in 遍历的是自身和原型的可枚举属性
for(let i in child){
  console.log(i);
}
// b a

for(let i in child){
  if(child.hasOwnProperty(i)){
    console.log(i);
  }
}
//b

//object.keys() 相当于for...in + hasOwnProperty()形式
console.log(Object.keys(child)); //获取自身可枚举属性,不包括原型
//b

//打印出自己的属性,无论是否可枚举
console.log(Object.getOwnPropertyNames(child));
//b c

27.说下防抖和截流,以及怎样实现

防抖:在n秒后执行回调函数,如果在n秒内再触发事件,重新计算时间。

function dance(fn,delay){
  var timeId;
  return function (){
    clearTimeout(timeId);
    timeId = setTimeout(fn,delay);
  }
}

function callback(){
  console.log("网络请求中……");
}

var preventDance = dance(callback,500);
var btn = document.getElementById("btn");
btn.onclick = preventDance;

截流:顾名思义就是限流的意思,在规定的时间内只能执行一次回调函数

28.target 和 currentTarget的区别

<div id='A'>
  <div id='B'></div>
</div>

var a = document.getElementById('A');
a.addEventListener('click',function(e){
  console.log(e.target);
  console.log(e.currentTarget);
},false);

所以最终的结论是:target是点击哪个元素,就代表谁。而currentTarget是事件绑定的对象
https://www.jianshu.com/p/ee83be054682

29.父元素宽高固定200px,里面是宽高未知的图片,怎样使图片水平垂直居中

<div class="parent">
  <img class="child"  src="images/a.jpg"/>
</div>
image.png
.parent{
  position:relative;
  width:200px;
  height:200px;
  border:1px solid red;
}
 /* 方式一 flex */
.parent{
  position:relative;
  width:200px;
  height:200px;
  border:1px solid red;
 
  display:flex;
  justify-content:center;
  align-items:center;
}
/* 方式二 position + transform */
.child{
  position:absolute;
  left:50%;
  top:50%;
  transform:translate(-50%,-50%);
}
 /* 方式三:table-cell */
.parent{
  position:relative;
  width:200px;
  height:200px;
  border:1px solid red;
 
  display:table-cell;
  text-align:center;
  vertical-align:middle;
}
/* 方式四  */
/* 注意:position:absolute 和 float:left都会隐式将元素的display转化
为display:inline-block */
.child{
  position:absolute;
  left:0;
  top:0;
  bottom:0;
  right:0;
  margin:auto;
}
/* 方式五 grid */
.parent {
    width: 200px;
    height: 200px;
    border: 1px solid red;
    position: relative;
    display: grid;
}
.child {
    justify-self: center;
    align-self: center;
 }

30.响应式布局中,子元素的宽度是父元素宽度的80%,怎样使子元素的宽高比是2:1 (css实现)

<div class="parent">
  <div class="child"></div>
</div>
.parent{
  width:100%;
  border:1px solid red;
}
/* 方法一 */
.child{
  width:80vw;
  height:40vw;
}
/* 方式二 */
.child{
  width:80%;
  height:0;
  padding-bottom:40%;
}
/* padding 在使用百分比时,相对的是父元素的宽度 */

31.上下高度固定,中间自适应

<div class='wrapper'>
  <div class="top"></div>
  <div class="center"></div>
  <div class="bottom"></div>
</div>
/* 方式一: 上下固定,中间超出内容滚动 */
.wrapper>div{
  position:absolute;
}
.top{
  top:0;
  height:100px;
  width:100%;
}
.center{
  top:100px;
  bottom:100px;
  width:100%;
  overflow:auto;
}
.bottom{
  bottom:0;
  height:100px;
  width:100%;
}
/* 方式二: grid 上下固定,中间超出部分会将footer挤出屏幕外 */
html,body{
  width:100%;
  heigth:100%;
}
.wrapper{
  display:grid;
  height:100%;
  grid-template-rows:100px auto 100px;
}
/* 方式三:flex */
.wrapper{
  display:flex;
  flex-direction:column;
}
.top{
  height:100px;
  flex:0 0 auto;
}
.center{
  flex:1 1 auto;
}
.bottom{
  height:100px;
  flex: 0 0 auto;
}
/* 方式四:table */
html,body{
  width:100%;
  height:100%;
}
.wrapper{
  height:100%;
  display:table:
}
.wrapper > div{
  display:table-row;
}
.top, .bottom{
  height:100px;
}
/*table-row 中必须有内容,否则不显示*/

32.输出结果是什么?

  var x = 1;
  var kit = {
     x: 2,
     buf: {
       x: 3,
       fac() {
         return this.x;
        },
        til: () => {
          return this.x;
        }
      }
   };
   var foo = kit.buf.fac;
   console.log(foo());
   console.log(kit.buf.fac());
   console.log(kit.buf.til());
//1 3 1

注意:这道题主要考察this指向问题,箭头函数是绑定外侧this,也就是指向window的,还有setTimeout和setInterval里面的this也是指向外层window。

var x = 5;
setTimeout(function() {
    var x = 3;
    console.log(this.x); 
}, 1000);
// 5

33. 输出结果是什么,为什么

  var k =10;
  function fac(){
    k =10;
    return;
    function k(){}
  }
  fac();
  console.log(k);
  // 1

此题主要理解函数的变量提升,执行fac时相当于这样:

function fac(){
  var k = function (){}
  k =10;
  return;
}

所以k改变的是局部变量,所以打印出来当然还是1。

34.各种小算法

add(2)(3) //5

function add(num){
  var sum = num;
  return function (x){
    sum +=x;
    return sum;
  }
}

add(2)(3)(4)(5)(6) //20

function add(num){
  var sum=num,index=1;
  var temp = function (x){
    index++;
    sum += x;
    if(index==5){
      return sum;
    }else{
      return temp;
    }
  }
  return temp;
}

add(2)(3)返回add()函数,只有不传参数时返回值,比如add(2)(3)() //输出5

function add(num){
  var sum;
  if(arguments.length==0){
    return 0;
  }else{
    sum =num;
  }
  var temp = function (x){
    if(arguments.length==0){
      return sum;
    }else{
      sum += x;
      return temp;
    }
  }
  return temp;
}

27、说下BFC

18. call() apply() bind()区别

https://wangdoc.com/javascript/oop/this.html

vue 无限循环列表,要加一个key

computed 和 watch区别

上一篇 下一篇

猜你喜欢

热点阅读