stay hungry stay foolish

前端面试题

JS作用域

var a=10;
function aaa(){
  console.log(a);
  var a=20;
}
aaa(); //undefined

解释:aaa函数里的变量进行了提升,相当于先声明了变量var a,后面再进行赋值操作。

function aa(){ var a=b=10 };
console.log(b); //10

解释:var a=b=10,相当于var a;b=10;a=b;,未声明的b变成了全局变量

function Foo() {
    getName = function () { console.log(1); };
    return this;
}
Foo.getName = function () { console.log(2); };
Foo.prototype.getName = function () { console.log(3); };
var getName = function () { console.log(4); };
function getName() { console.log(5); }
 
//请写出以下输出结果:
Foo.getName(); //2
getName(); //4
Foo().getName(); //1
getName(); //1
new Foo.getName(); //2
new Foo().getName(); //3
new new Foo().getName();//3

解释:

  • 第一问,调用Foo的函数属性getName,直接执行Foo.getName
  • 第二问,最后的函数声明进行了函数提升,所以最被var getName那一行的函数表达式给覆盖了
  • 第三问,执行Foo()后重新用函数表达式覆盖了getName函数,最后返回的this相当于window对象
  • 第四问,结果同上
  • 第五问,成员运问符号.的优先级(18)大于new无参运算符的优先级(17),因此这一问的代码相当于new (Foo.getName)()
  • 第六问,new带参运算符优先级(18)等于成员运算符.的优先级(18),因此这一问的代码相当于(new Foo()).getName()
  • 第七问,根据优先级,这一问的代码相当于new (new Foo()).getName)()

JS运算符

运算符优先级总结(从上到下依次递减)

  • ()
  • 成员符号., [], new()
  • new
  • 一元运算符
    • 后置++, 后置–
    • 前置++, 前置–, !, ~, 一元加法+, 一元减法-, typeof, void, delete, await
  • 二元运算符
    • **
    • *, /, %
    • +, -
    • >>, <<, >>>
    • <, <=, >, >=, in, instanceof
    • =, !=, ===, !==
    • &
    • |
    • &&
    • ||
    • ??
    • ?:
    • =
  • yield, yield*
  • ,
var a = 1;
console.log(a++-1+a) //2

解释:第一个a++返回的值为1,后面一个a返回的值为2,相当于1-1+2

var a = 1;
console.log(++a-1+a) //3

解释:第一个++a返回的值为2,后面一个a返回的值也为2,相当于2-1+2