2015
年6
月正式发布了。它的目标,是使得 JS 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。接下来咱们来看看 20 道棘手的面试题,通过做题,顺带提升一下咱们的 JS 的技能。ES5
和ES6
的区别吗?主题: JavaScript难度: ⭐⭐⭐
const greetings = (name) => {
return `hello ${name}`;
}
const greetings = name => `hello ${name}`;
const
表示无法修改变量的原始值。需要注意的是,const
表示对值的常量引用,咱们可以改变被引用的对象的属性值,但不能改变引用本身。
const NAMES = [];
NAMES.push('Jim');
console.log(NAMES.length === 1); // true
NAMES = ['Steve', 'John']; // error
let
, const
会创建块级作用域,不会像 var
声明变量一样会被提升。undefined
时使用默认参数值。
function multiply (a, b = 2) {
return a * b;
}
multiply(5); // 10
class
关键字)、构造函数(constructor
关键字)和 extend
关键字(用于继承)的语言支持。for...of
语句创建一个遍历可迭代对象的循环。
const obj1 = { a: 1, b: 2 }
const obj2 = { a: 2, c: 3, d: 4}
const obj3 = {...obj1, ...obj2}
Promises
通过方法链接和简洁的错误处理来提高可读性。
const isGreater = (a, b) => {
return new Promise ((resolve, reject) => {
if(a > b) {
resolve(true)
} else {
reject(false)
}
})
}
isGreater(1, 2)
.then(result => {
console.log('greater')
})
.catch(result => {
console.log('smaller')
})
const myModule = { x: 1, y: () => { console.log('This is ES5') }}
export default myModule;
import myModule from './myModule';
主题: JavaScript难度: ⭐⭐⭐
IIFE
是一个立即调用的函数表达式,它在创建后立即执行
(function IIFE(){
console.log( 'Hello!' );
})();
// 'Hello!'
IIFE
中使用的所有变量(与任何其他普通函数一样)在其作用域之外都是不可见的。主题: JavaScript难度: ⭐⭐⭐
Object.prototype
属性中使用 function
。class
。thisObject
。如果一个标准函数回调与一堆箭头函数混合在一起,那么作用域就有可能变得混乱。this
指向。主题: JavaScript难度: ⭐⭐⭐
Symbol
是一种新的、特殊的对象,可以用作对象中惟一的属性名。使用 Symbol
替换string
可以避免不同的模块属性的冲突。还可以将Symbol
设置为私有,以便尚无直接访问Symbol
权限的任何人都不能访问它们的属性。Symbol
是JS新的基本数据类型。与number
、string
和boolean
原始类型一样,Symbol
也有一个用于创建它们的函数。与其他原始类型不同,Symbol
没有字面量语法。创建它们的唯一方法是使用以下方法中的Symbol
构造函数let symbol = Symbol();
主题: JavaScript难度: ⭐⭐⭐
Object.create,slice
或库函数。Redux
和rx.js
项目中经常使用此特性。
function putDookieInAnyArray(arr) {
return [...arr, 'dookie'];
}
const result = putDookieInAnyArray(['I', 'really', 'don't', 'like']);
// ['I', 'really', 'don't', 'like', 'dookie']
const person = {
name: 'Todd',
age: 29,
};
const copyOfTodd = { ...person };
function addFiveToABunchOfNumbers(...numbers) {
return numbers.map(x => x + 5);
}
const result = addFiveToABunchOfNumbers(4, 5, 6, 7, 8, 9, 10);
// [9, 10, 11, 12, 13, 14, 15]
const [a, b, ...rest] = [1, 2, 3, 4]; // a: 1, b: 2, rest: [3, 4]
const { e, f, ...others } = {
e: 1,
f: 2,
g: 3,
h: 4,
}; // e: 1, f: 2, others: { g: 3, h: 4 }
主题: JavaScript难度: ⭐⭐⭐
// ES5 Function Constructor
function Person(name) {
this.name = name;
}
// ES6 Class
class Person {
constructor(name) {
this.name = name;
}
}
Person
类的Student
子类并添加一个studentId
字段,以下是两种方式的使用:
// ES5 Function Constructor
function Student(name, studentID) {
// 调用你类的构造函数以初始化你类派生的成员。
Person.call(this. name)
// 初始化子类的成员。
this.studentId = studentId
}
Student.prototype = Object.create(Person.prototype)
Student.prototype.constructor = Student
// ES6 Class
class Student extends Person {
constructor(name, studentId) {
super(name)
this.studentId = studentId
}
}
.call
和 .apply
区别是啥?主题: JavaScript难度: ⭐⭐⭐
.call
和.apply
均用于调用函数,并且第一个参数将用作函数中this
的值。但是,.call
将逗号分隔的参数作为下一个参数,而.apply
将参数数组作为下一个参数。简单记忆法:C用于call
和逗号分隔,A用于apply
和参数数组。function add(a, b) {
return a + b;
}
console.log(add.call(null, 1, 2)); // 3
console.log(add.apply(null, [1, 2])); // 3
主题: JavaScript难度: ⭐⭐⭐
class
可以避免构造函数中使用new的常见错误(如果构造函数不是有效的对象,则使构造函数抛出异常)。super.method()
代替ParentConstructor.prototype.method.call(this)
或Object.getPrototypeOf(Object.getPrototypeOf(this)).method.call(this)
主题: JavaScript难度: ⭐⭐⭐
Object.freeze
来实现枚举
var DaysEnum = Object.freeze({
'monday': 1,
'tuesday': 2,
'wednesday': 3,
...
})
var DaysEnum = {
'monday': 1,
'tuesday': 2,
'wednesday': 3,
...
}
Object.freeze(DaysEnum)
let day = DaysEnum.tuesday
day = 298832342 // 不会报错
Object.freeze()
和 const
的区别主题: JavaScript难度: ⭐⭐⭐
const
和Object.freeze
是两个完全不同的概念。const
声明一个只读的变量,一旦声明,常量的值就不可改变:
const person = {
name: 'Leonardo'
};
let animal = {
species: 'snake'
};
person = animal; // ERROR 'person' is read-only
Object.freeze
适用于值,更具体地说,适用于对象值,它使对象不可变,即不能更改其属性。
let person = {
name: 'Leonardo'
};
let animal = {
species: 'snake'
};
Object.freeze(person);
person.name = 'Lima'; //TypeError: Cannot assign to read only property 'name' of object
console.log(person);
主题: JavaScript难度: ⭐⭐⭐⭐
var
(或函数声明)出现在一个作用域内,这个声明就被认为属于整个作用域,并且可以在任何地方访问。
var a = 2
foo() // 正常运行, foo 已被提升
function foo() {
a = 3
console.log(a) // 3
var a
}
console.log( a ) // 2
主题: JavaScript难度: ⭐⭐⭐⭐
主题: JavaScript难度: ⭐⭐⭐⭐
let
和const
跟 var
、class
和function
一样也会被提升,只是在进入作用域和被声明之间有一段时间不能访问它们,这段时间是临时死区(TDZ)。
//console.log(aLet) // would throw ReferenceError
let aLet;
console.log(aLet); // undefined
aLet = 10;
console.log(aLet); // 10
主题: JavaScript难度: ⭐⭐⭐⭐
this/arguments
时,由于箭头函数本身不具有this/arguments
,因此它们取决于外部上下文this
即对象本身。主题: JavaScript难度: ⭐⭐⭐⭐
WeakMap
。
var map = new WeakMap();
var pavloHero = {
first: 'Pavlo',
last: 'Hero'
};
var gabrielFranco = {
first: 'Gabriel',
last: 'Franco'
};
map.set(pavloHero, 'This is Hero');
map.set(gabrielFranco, 'This is Franco');
console.log(map.get(pavloHero)); //This is Hero
map
内部键的弱引用。弱引用意味着如果对象被销毁,垃圾收集器将从WeakMap
中删除整个条目,从而释放内存。主题: JavaScript难度: ⭐⭐⭐⭐
function foo(){ }();
IIFE
代表立即调用的函数表达式。JS解析器读取函数foo(){}();
作为函数foo(){}
和();
,前者是一个函数声明,后者(一对括号)是尝试调用一个函数,但没有指定名称,因此它抛出Uncaught SyntaxError: Unexpected token
异常。void
操作符:void function foo(){ }();
。不幸的是,这种方法有一个问题。给定表达式的求值总是undefined
的,所以如果IIFE 函数有返回值,则不能使用它,如下所示:
const foo = void
function bar() {
console.log('前端小智')
return 'foo';
}();
console.log(foo); // undefined
主题: JavaScript难度: ⭐⭐⭐⭐
new MyNamespace.MyModule.MyClass(arguments)
)。scheme
或辅助方法来实现原型中的类。主题: JavaScript难度: ⭐⭐⭐⭐⭐
var map = new Map()
var weakmap = new WeakMap()
(function() {
var a = {
x: 12
};
var b = {
y: 12
};
map.set(a, 1);
weakmap.set(b, 2);
})()
{x:12}
和{y:12}
。垃圾收集器继续运行,并从 WeakMa
中删除键b
指针,还从内存中删除了{y:12}
。Map
的情况下,垃圾收集器不会从Map
中删除指针,也不会从内存中删除{x:12}
。WeakMap
允许垃圾收集器执行其回收任务,但Map
不允许。对于手动编写的 Map
,数组将保留对键对象的引用,以防止被垃圾回收。但在WeakMap
中,对键对象的引用被“弱”保留,这意味着在没有其他对象引用的情况下,它们不会阻止垃圾回收。主题: JavaScript难度: ⭐⭐⭐⭐⭐
function curry(fn) {
if (fn.length === 0) {
return fn;
}
function _curried(depth, args) {
return function(newArgument) {
if (depth - 1 === 0) {
return fn(...args, newArgument);
}
return _curried(depth - 1, [...args, newArgument]);
};
}
return _curried(fn.length, []);
}
function add(a, b) {
return a + b;
}
var curriedAdd = curry(add);
var addFive = curriedAdd(5);
var result = [0, 1, 2, 3, 4, 5].map(addFive); // [5, 6, 7, 8, 9, 10]
主题: JavaScript难度: ⭐⭐⭐⭐⭐
let person = {
name: 'Leonardo',
profession: {
name: 'developer'
}
};
Object.freeze(person);
person.profession.name = 'doctor';
console.log(person); //output { name: 'Leonardo', profession: { name: 'doctor' } }
function deepFreeze(object) {
let propNames = Object.getOwnPropertyNames(object);
for (let name of propNames) {
let value = object[name];
object[name] = value && typeof value === 'object' ?
deepFreeze(value) : value;
}
return Object.freeze(object);
}
let person = {
name: 'Leonardo',
profession: {
name: 'developer'
}
};
deepFreeze(person);
person.profession.name = 'doctor'; // TypeError: Cannot assign to read only property 'name' of object
本文完
联系客服