资讯专栏INFORMATION COLUMN

快速掌握JavaScript面试基础知识(一)

acrazing / 2974人阅读

摘要:根据调查,自年一来,是最流行的编程语言。在一个函数体中声明的变量和函数,周围的作用域内无法访问。也就是说被大括号包围起来的区域声明的变量外部将不可访问。一个常见的误解是使用声明的变量,其值不可更改。

译者按: 总结了大量JavaScript基本知识点,很有用!

原文: The Definitive JavaScript Handbook for your next developer interview

为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习。

根据StackOverflow调查, 自2014年一来,JavaScript是最流行的编程语言。当然,这也在情理之中,毕竟1/3的开发工作都需要一些JavaScript知识。因此,如果你希望在成为一个开发者,你应该学会这门语言。

这篇博客的主要目的是将所有面试中常见的概念总结,方便你快速去了解。
(译者按:鉴于本文内容过长,方便阅读,将分为三篇博客来翻译。)

类型和类型转换

在JavaScript中有7个内置类型:nullundefinedbooleannumberstringobject,和symbol(ES6)。

除了object以外,其它都叫做基本类型。

typeof 0              // number
typeof true           // boolean
typeof "Hello"        // string
typeof Math           // object
typeof null           // object  !!
typeof Symbol("Hi")   // symbol (New ES6)

Null vs. Undefined

Undefined表示未定义。对于没有初始化的变量、函数调用时候未提供的函数参数、缺失的对象属性,它们的默认值就是undefined。如果一个函数没有返回语句,那么默认的返回值也是undefined

NUll表示值为空。一个变量我们可以将其赋值为null,表示当前的没有值。

隐式转换

请看下面的例子:

var name = "Joey";
if (name) {
  console.log(name + " doesn"t share food!")  // Joey doesn’t share food!
}

if语句的条件判断中,name从字符串转换为布尔型。在if的代码块中,在控制台将name原原本本打印出来。你知道在什么情况下字符串会转换为真,什么时候为假么?

""0nullundefined, NaN, false 会自动转换为false。其它的都会转换为真:

Boolean(null)         // false
Boolean("hello")      // true 
Boolean("0")          // true 
Boolean(" ")          // true 
Boolean([])           // true 
Boolean(function(){}) // true

空数组、对象、函数定义都会自动转换为真。

String & Number之间的转换

第一个你要非常小心的是+操作符。因为它同时用于数字相加和字符串拼接。

*,/,-只用于数字运算,当这些操作符和字符串一起使用,那么字符串会被强制转换为数字。

1 + "2" = "12"
"" + 1 + 0 = "10"
"" - 1 + 0 = -1
"-9
" + 5 = "-9
5"
"-9
" - 5 = -14
"2" * "3" = 6
4 + 5 + "px" = "9px"
"$" + 4 + 5 = "$45"
"4" - 2 = 2
"4px" - 2 = NaN
null + 1 = 1

== vs. ===

一个广泛被接受的认知就是:==判断值是否相等,===同时判断值是否相等和类型是否相同。但是,这里有些误解。

实际上,==在验证相等性的时候,会对类型不同的值做一个类型转换。===对要判断的值不做类型转换。

2 == "2"            // True
2 === "2"           // False
undefined == null   // True
undefined === null  // False

类型转换有很多取巧的地方,要注意:

let a = "0";
console.log(Boolean(a)); // True
let b = false;
console.log(Boolean(b)); // False

你认为下面的相等判断会输出什么值呢?

console.log(a == b);

实际上会返回true。知道为什么吗?
如果你将一个布尔类型的和非布尔类型的判断,JavaScript会将布尔类型的转换为数字然后再比对。
执行过程如下:

"0" == false   (1)
"0" == 0       (2)
 0  == 0       (3)

所以,最终变成了0==0,当然返回true啦。

如果你想看完整的资料,请查看ES5的官方文档。

如果想看cheat sheet, 点击这里。

一些比较容易掉坑的比较,我在这里列出来:

false == ""  // true
false == []  // true
false == {}  // false
"" == 0      // true
"" == []     // true
"" == {}     // false
0 == []      // true
0 == {}      // false
0 == null    // false
值 vs. 引用

对于基本类型的值,赋值是通过值拷贝的形式;比如:nullundefinedbooleannumberstring和ES6的symbol。对于复杂类型的值,通过引用拷贝的形式赋值。比如:对象、对象包括数组和函数。

var a = 2;        // "a" hold a copy of the value 2.
var b = a;        // "b" is always a copy of the value in "a"
b++;
console.log(a);   // 2
console.log(b);   // 3
var c = [1,2,3];
var d = c;        // "d" is a reference to the shared value
d.push( 4 );      // Mutates the referenced value (object)
console.log(c);   // [1,2,3,4]
console.log(d);   // [1,2,3,4]
/* Compound values are equal by reference */
var e = [1,2,3,4];
console.log(c === d);  // true
console.log(c === e);  // false

如果想对复杂类型的值进行值拷贝,你需要自己去对所有子元素进行拷贝。

const copy = c.slice()    // "copy" 即使copy和c相同,但是copy指向新的值
console.log(c);           // [1,2,3,4]
console.log(copy);        // [1,2,3,4]
console.log(c === copy);  // false

Fundebug提供实时、专业的错误监控服务,为您的线上代码保驾护航,欢迎大家免费使用!

作用域(Scope)

作用域值程序的执行环境,它包含了在当前位置可访问的变量和函数。

全局作用域是最外层的作用域,在函数外面定义的变量属于全局作用域,可以被任何其他子作用域访问。在浏览器中,window对象就是全局作用域。

局部作用域是在函数内部的作用域。在局部作用域定义的变量只能在该作用域以及其子作用域被访问。

function outer() {
  let a = 1;
  function inner() {
    let b = 2;
    function innermost() {
      let c = 3;
      console.log(a, b, c);   // 1 2 3
    }
    innermost();
    console.log(a, b);        // 1 2 — "c" is not defined
  }
  inner();
  console.log(a);             // 1 — "b" and "c" are not defined
}
outer();

你可以将作用域想象成一系列不断变小的门。如果一个个子不高的人可以穿过最小的门(局部最小作用域),那么必然可以穿过任何比它大的门(外部作用域)。

提升(Hoisting)

在编译过程中,将varfunction的定义移动到他们作用域最前面的行为叫做提升。

整个函数定义会被提升。所以,你可以在函数还未定义之前调用它,而不用担心找不到该函数。

console.log(toSquare(3));  // 9

function toSquare(n){
  return n*n;
}

变量只会被部分提升。而且只有变量的声明会被提升,赋值不会动。

letconst不会被提升。

{  /* Original code */
  console.log(i);  // undefined
  var i = 10
  console.log(i);  // 10
}

{  /* Compilation phase */
  var i;
  console.log(i);  // undefined
  i = 10
  console.log(i);  // 10
}
// ES6 let & const
{
  console.log(i);  // ReferenceError: i is not defined
  const i = 10
  console.log(i);  // 10
}
{
  console.log(i);  // ReferenceError: i is not defined
  let i = 10
  console.log(i);  // 10
}
函数表达式和函数声明

函数表达式

一个函数表达式是在函数执行到函数表达式定义的位置才开始创建,并被使用。它不会被提升。

var sum = function(a, b) {
  return a + b;
}

函数声明

函数声明的函数可以在文件中任意位置调用,因为它会被提升。

function sum(a, b) {
  return a + b;
}
变量:var,let和const

在ES6之前,只能使用var来声明变量。在一个函数体中声明的变量和函数,周围的作用域内无法访问。在块作用域iffor中声明的变量,可以在iffor的外部被访问。

注意:如果没有使用var,let或则const关键字声明的变量将会绑定到全局作用域上。

function greeting() {
  console.log(s) // undefined
  if(true) {
    var s = "Hi";
    undeclaredVar = "I am automatically created in global scope";
  }
  console.log(s) // "Hi"
}
console.log(s);  // Error — ReferenceError: s is not defined
greeting();
console.log(undeclaredVar) // "I am automatically created in global scope"

ES6的letconst都是新引入的关键字。它们不会被提升,而且是块作用域。也就是说被大括号包围起来的区域声明的变量外部将不可访问。

let g1 = "global 1"
let g2 = "global 2"
{   /* Creating a new block scope */
  g1 = "new global 1"
  let g2 = "local global 2"
  console.log(g1)   // "new global 1"
  console.log(g2)   // "local global 2"
  console.log(g3)   // ReferenceError: g3 is not defined
  let g3 = "I am not hoisted";
}
console.log(g1)    // "new global 1"
console.log(g2)    // "global 2"

一个常见的误解是:使用const声明的变量,其值不可更改。准确地说它不可以被重新赋值,但是可以更改。

const tryMe = "initial assignment";
tryMe = "this has been reassigned";  // TypeError: Assignment to constant variable.
// You cannot reassign but you can change it…
const array = ["Ted", "is", "awesome!"];
array[0] = "Barney";
array[3] = "Suit up!";
console.log(array);     // [“Barney”, “is”, “awesome!”, “Suit up!”]
const airplane = {};
airplane.wings = 2;
airplane.passengers = 200;
console.log(airplane);   // {passengers: 200, wings: 2}
后续

快速掌握JavaScript面试基础知识(二)

版权声明:
转载时请注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2018/01/15/the-definitive-javascript-handbook-for-a-developer-interview/

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/92677.html

相关文章

  • 快速掌握JavaScript面试基础知识(三)

    摘要:第一部分请点击快速掌握面试基础知识一关键字如果使用关键字来调用函数式很特别的形式。该对象默认包含了指向原构造函数的属性。接下来通过例子来帮助理解属性包含了构造函数以及构造函数中在上定义的属性。也就是说,的回调函数后执行。 译者按: 总结了大量JavaScript基本知识点,很有用! 原文: The Definitive JavaScript Handbook for your next...

    qieangel2013 评论0 收藏0
  • 快速掌握JavaScript面试基础知识(二)

    摘要:第一部分请点击快速掌握面试基础知识一闭包闭包由一个函数以及该函数定义是所在的环境组成。当匿名函数执行的时候,的值为。这个问题可以改用后面会介绍方法来解决,通过对每一个匿名函数构建独立的外部作用域来实现。 译者按: 总结了大量JavaScript基本知识点,很有用! 原文: The Definitive JavaScript Handbook for your next develope...

    fyber 评论0 收藏0
  • 前端经典文章

    摘要:上周末看这篇文章时,偶有灵光,所以,分享出来给大家一起看看前端面试四月二十家前端面试题分享请各位读者添加一下作者的微信公众号,以后有新的文章,将在微信公众号直接推送给各位,非常感谢。 前端切图神器 avocode 有了这个神器,切图再也腰不酸,腿不疼了。 这一次,彻底弄懂 JavaScript 执行机制 本文的目的就是要保证你彻底弄懂javascript的执行机制,如果读完本文还不懂,...

    lowett 评论0 收藏0
  • 前端优化 - 收藏集 - 掘金

    摘要:虽然有着各种各样的不同,但是相同的是,他们前端优化不完全指南前端掘金篇幅可能有点长,我想先聊一聊阅读的方式,我希望你阅读的时候,能够把我当作你的竞争对手,你的梦想是超越我。 如何提升页面渲染效率 - 前端 - 掘金Web页面的性能 我们每天都会浏览很多的Web页面,使用很多基于Web的应用。这些站点看起来既不一样,用途也都各有不同,有在线视频,Social Media,新闻,邮件客户端...

    VincentFF 评论0 收藏0
  • 前端相关大杂烩

    摘要:希望帮助更多的前端爱好者学习。前端开发者指南作者科迪林黎,由前端大师倾情赞助。翻译最佳实践译者张捷沪江前端开发工程师当你问起有关与时,老司机们首先就会告诉你其实是个没有网络请求功能的库。 前端基础面试题(JS部分) 前端基础面试题(JS部分) 学习 React.js 比你想象的要简单 原文地址:Learning React.js is easier than you think 原文作...

    fuyi501 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<