回答一下这 10 个最常见的 Javascript 问题

    |     2020年7月31日   |   html/css/js, web前端技术   |     0 条评论   |    818

下面整理了 JavaScript 里最常被问到的 10 个问题。它们大多落在基础上:闭包、Promise、变量提升、类 等。难度不算高,但面试里反复出现,值得一次对齐口径。

适合刚开始学 JS 的读者:先看懂例子,再对照自己的代码想一遍「如果改掉某一行会怎样」。答案不是唯一标准,这里是便于记忆的讲法。

原文:https://dev.to/duomly/10-most-common-javascript-questions-answered-1083。

一、闭包是什么

闭包是「函数 bundled 在一起」的组合:内部函数可以访问自己的变量,也能访问外部函数的变量。最直白的办法是看例子:

function outer() {
  var name = 'Maria';
  function inner() {
    console.log(name);
  }
  inner();
}
outer();
// 'Maria'

inner() 能读到父函数里的 name,所以调用 outer() 会打印 Maria。内部函数也能看到外部的参数对象;若内外形参同名,内部会盖住外部:

function outer(a, b) {
  const inner = (a, b) => console.log(a, b);
  inner(1, 2);
}
outer('Alice', 'Mark');
// returns 1, 2

闭包最常见的用途,是让一个函数返回另一个仍能「记住」外层变量的函数。

二、DOM 是什么

DOM 是文档对象模型,网站的面向对象表示,可用 JavaScript 修改颜色、位置、尺寸等。选节点常用:

  • getElementById():按 id 取一个元素;
  • getElementsByName():按 name 取节点集合;
  • getElementsByTagName():按标签名取集合;
  • getElementsByClassName():按类名取集合;
  • querySelector():按 CSS 选择器取第一个匹配。

改结构时还会用到 appendChild() 或属性 innerHTML(它是属性,不是函数)。

三、Promise 是什么

Promise 是异步方案,用来替代层层回调和部分事件写法。ES6 把它做成语言内置对象。两个特点:状态不受外界随意改写;一旦从进行中离开,就不会再变。

三种状态:Pending(进行中)、Fulfilled / Resolved(成功)、Rejected(失败)。成功走 resolve 并进入 then();失败走 reject 并进入 catch()。同类方案还有 async/await 和回调。

四、原型是什么

通常指 prototype(显式原型)和 __proto__(隐式原型)。对象沿原型链继承方法和属性,Object.prototype 在链顶。给构造函数补充成员时,写在 Constructor.prototype 上:

function Animal(name, kind, age) {
  this.name = name;
  this.kind = kind;
  this.age = age;
}

Animal.prototype.ownerName = 'Mark';

这样每个 new Animal(...) 实例都能顺着原型读到 ownerName。原文写成 Animal.prototype.ownerName('Mark') 会把原型当函数调用,运行会报错。

五、变量提升是什么

提升(hoisting) 会把声明提到当前作用域顶部:函数作用域内提到函数顶,全局则提到全局顶。所以可以「先用后声明」var 变量,避免部分 ReferenceError。

name = 'Ted';
console.log(name);
var name;
// 'Ted'

var name;
name = 'Ted';
console.log(name);
// 'Ted'

只用 var 声明、尚未赋值时,值是 undefined。let / const 也有提升,但在初始化前处于暂时性死区,不能提前读。const 声明时必须同时初始化。

六、对象是什么

对象是带属性和方法的数据。字符串、数值、数组、函数在语言里都可以按对象来用。属性描述特征(长度、宽高),方法是能执行的动作(提交表单、取年份)。

var student = {
  firstName: 'Alice',
  lastName: 'Jones',
  age: 21,
  sayHi: function() {
    return 'Hi, I am ' + this.firstName;
  }
}

上面是三个属性加一个方法。箭头函数不会绑定自己的 this,写在对象字面量里当方法时,this.firstName 往往不是你以为的那个对象,所以这里改成普通函数。

七、函数是什么

函数是可被多次调用的代码块,typeof 结果为 "function"。它也有属性和方法,因此函数也是对象。声明或表达式都以关键字 function 开头(箭头函数除外)。定义时括号里是形参,调用时传入的是实参。

function calculate(x, y) {
  return x * y;
}

calculate(2, 5);

八、纯函数是什么

相同输入永远得到相同输出,且不依赖、不修改函数外部的可观察状态。像中学函数:一个输入只对应一个输出;不同输入可以撞上同一输出,但同一输入不能给出两个结果。

  • 相同输入 → 相同输出;
  • 没有可观察到的副作用。

九、构造函数是什么

在 JavaScript 里,用 new 调用的函数都会走构造过程:内部 this 指向新对象,新对象的原型指向构造函数的 prototype。若没有显式 return 对象,就隐式返回这个 this。

function Person(name, age) {
  this.name = name;
  this.age = age;
}

var man = new Person('Mark', 23);
console.log(man);
// { name: 'Mark', age: 23 }

原文用箭头函数当构造器。箭头函数没有自己的 this,也不能被 new,运行会 TypeError,所以改成普通函数。

十、类是什么

ES6 起可以用 class 声明类,本质仍是函数。类里要有 constructor(),每次 new 都会调用,属性写在构造里。 用 extends 基于已有类派生。React 的类组件就是典型用法。

概念 一句话 容易踩的坑
闭包 内函数记住外层变量 循环里用 var 绑定时容易串值
Promise 异步的一次性状态机 已敲定的状态不会再变
提升 var / 函数声明上移 let/const 有暂时性死区
原型 实例沿链找方法和属性 给原型赋值不要写成函数调用
构造 / 类 new 出来的对象 不要用箭头函数当构造器

一句话总结:这 10 问都围着作用域、异步、对象模型和类型系统转:例子能跑通,口径才能在面试里站得住。

转载请注明来源:回答一下这 10 个最常见的 Javascript 问题
本文链接地址:https://ai.zhousir.top/?p=3000
回复 取消