JS简答题1

简答题

1. 请说出下列最终执行结果,并解释为什么?

var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6]();

答:执行结果是 10,因为执行顺序是先循环 10 次,给 a 数组中保存 10 个函数元素。当循环结束以后,全局变量 i 的值已经变为了 10,这个时候无论调用数组中的哪一个,打印结果都是 10.可以改为下面两种:

第一种:使用闭包
var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = (function () {
    console.log(i);
  })(i);
}
//依次打印出来 0 1 2 3 4 5 6 7 8 9
第二种:使用 let 因为 let 的块级作用域
var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); //6

2. 请说书此案列最终执行结果,并解释为什么?

var tmp = 123;
if (true) {
  console.log(tmp);
  let tmp;
}

答:会报错 因为 let 有块级作用域,块级作用域中的变量只能在声明以后才能使用,否则报错。这里 console.log 打印的是块级作用域中的 tmp,应该在声明之后使用。

3. 结合 ES6 语法,用最简单的方式找出数组中的最小值

var arr = [12, 34, 32, 89, 4];
console.log(Math.min(...arr)); //最简单
let minNum = (args) => Math.min(...args); //args
console.log(minNum(arr));

4. 请详细说明 var、let、const 三种声明变量的方式之间的具体差别

答:var 没有块级作用域,只有函数作用域和全局作用域;有变量提升:即可以先使用再声明。但是 let 和 const 有块级作用域,即{}。没有变量提升,需要在声明之后才可使用,否则会报错。同一个作用域内,let 和 const 不允许重复声明。const 声明常量,声明的时候就得赋值,且不可重新赋值。用 var 声明的全局变量,是顶层对象的属性;而用 let const 声明的全局变量不是顶层对象的属性。

5. 请说出下列代码最终输出结果,并解释为什么?

var a = 10;
var obj = {
  a: 20,
  fn() {
    setTimeout(() => {
      console.log(this.a);
    });
  },
};
obj.fn();

答:输出 20 原因:因为是 obj 调用的 fn 函数 所以 this 指向 obj this.a 即为 obj.a 并且箭头函数中的 this 指向声明时所在的作用域上下文的 this 这里是 obj.

6. 简述 Symbol 类型的用途

答:主要为对象添加独一无二的属性名,避免被覆盖。另外还可以实现对象中对私有成员的访问。

7. 说说什么是浅拷贝,什么是深拷贝?

答:浅拷贝是只拷贝一层,深层次对象级别的拷贝只拷贝引用,即:如果原对象的值发生了改变,那么浅拷贝中对应的值也会改变;深层次拷贝是每一层的数据都会拷贝出来,原对象的值改变,并不会影响拷贝的值。浅拷贝就是两个对象引用的是同一个内存空间,一个改变都改变;深拷贝就是两个对象,原对象还是用原来的存储空间。新对象自己开辟新空间,两个是互相独立的。互不影响。

//实现浅拷贝的方法一
function simpleClone(initialObj) {
  let obj = {};
  for (let key in initialObj) {
    obj[key] = initialObj[key];
  }
  return obj;
}
//实现浅拷贝的方法二
Object.assign(target, ...sources);
//实现深拷贝的方法一
function deepClone(initialObj) {
  return JSON.parse(JSON.stringify(obj));
}
//注:JSON不能够识别Function类型 深拷贝以后 Function会返回undefined 所以这个方法只能用于只有数据的对象

//递归方法实现深拷贝
function deeepClone(obj) {
  var newObj = obj.constructor === Array ? [] : {};
  //如果不是对象类型 就返回
  if (typeof obj !== "object") {
    return;
  }
  for (var i in obj) {
    newObj[i] = typeof obj[i] === "object" ? deepClone(obj[i]) : obj[i];
  }
  return newObj;
}

8. 请简述 TypeScript 与 JavaScript 之间的关系?

答:官方文档说:TypScript 是 JavaScript 的超集。我的理解是:第一:相比于 Python 或者 Java 等,JS 是一种弱类型的动态语言,因此只有在运行代码的时候,才会发现一些类型错误。所以有了 TS 语言,它在 JS 的基础上规范了类型注解和类型检查,要求开发者在书写时就写好类型注解,从而在编译时就能够有错误提示,降低了运行时出现的错误。第二:TS 能够具有和 babel 工具同样的作用,将 ES6+的语法降级,转成 ES5 等。

9. 请谈谈你所认为的 typescript 优缺点

答:优点:强化了 JS 的类型规范,有效规避 js 只有在运行时出现的错误,比 JS 少了类型判断的逻辑,可以将 ES6+的语法转换成 ES5 的语法,比较适合大型项目或者重构。缺点:如果是小型且紧急的项目,写类型注解比较耗时。

10. 描述引用计数的工作原理和优缺点

答:引用计数是 JS 垃圾回收的一种算法,工作原理:给变量设置引用数,判断它的引用数是否为 0,当关系改变时,修改引用数字。当引用数字为 0 时,立即进行垃圾回收。优点:当引用数字为 0 时,即发现垃圾时就立即回收。因此最大程度地减少了程序暂停。缺点:无法回收循环引用的对象且时间开销比较大。

11. 描述标记整理算法的工作流程

答:先遍历所有对象标记活动的对象,然后再一次遍历所有对象,先执行整理,移动对象的位置,将所有没有标记的对象地址连续起来,避免产生碎片化空间,然后清除这些没有标记的对象,回收相应的空间。

12.描述 V8 中新生代存储区垃圾回收的流程。

答:新生代的内存区分为两个同等大小的空间:使用空间为 from,空闲时间为 to。活动对象存储于 from 空间,采用标记整理法将活动对象复制给 to,from 和 to 交换空间完成空间释放。新生代垃圾回收过程采用复制算法 + 标记整理。

13. 描述增量标记算法在何时使用及工作原理

答:标记增量在老生代存储区中使用。先使用标记清除完成垃圾回收,再采用标记整理优化空间,并且在程序执行的间隙进行增量标记优化效率。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值