开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情
数据类型与栈堆
基础数据类型都是按值访问,因为我们可以直接操作保存在变量中的实际的值。 引用类型的值都是按引用访问的。在操作对象时,实际上是在操作对象的引用而不是实际的对象。
内存空间与垃圾回收机制
标记清除和引用计数。
执行上下文
运行环境
- 全局环境:JavaScript代码运行起来会首先进入该环境
- 函数环境:当函数被调用执行时,会进入当前函数中执行代码
- eval(不建议使用,可忽略)
变量对象(VO)
变量提升 function声明会比var声明优先级更高一点。
function test() {
function foo() {
return 2;
}
var a;
console.log(a);
console.log(foo());
a = 1;
}
test();
活动对象(AO)
进入执行阶段之前,变量对象中的属性都不能访问!但是进入执行阶段之后,变量对象转变为了活动对象,里面的属性都能被访问了,然后开始进行执行阶段的操作。
区别:他们其实都是同一个对象,只是处于执行上下文的不同生命周期。不过只有处于函数调用栈栈顶的执行上下文中的变量对象,才会变成活动对象。
暂时性死区
console.log(a);
let a = 10;
变量定义了,但是没有初始化。.let/const声明的变量,仍然会提前被收集到变量对象中,但和var不同的是,let/const定义的变量,不会在这个时候给他赋值undefined。
作用域与作用域链
作用域是一套规则。而作用域链,则是作用域的具体实现。
作用域链,是由当前环境与上层环境的一系列变量对象组成,它保证了当前执行环境对符合访问权限的变量和函数的有序访问。
词法环境
通俗来说,词法环境就是一套约定好的规则。我们写代码,应该按照这个规则来。JS引擎对JS源码进行词法分析,也是按照这个规则来。
V8引擎是如何工作的
闭包
闭包是一种特殊的对象。
它由两部分组成。执行上下文(代号A),以及在该执行上下文中创建的函数(代号B)。
当B执行时,如果访问了A中变量对象中的值,那么闭包就会产生。
this指向
this的指向,是在函数被调用的时候确定的。 也就是执行上下文被创建时确定的。
在函数执行过程中,this一旦被确定,就不可更改了。
函数中this的指向
在一个函数上下文中,this由调用者提供,由调用函数的方式来决定。如果调用者函数,被某一个对象所拥有,那么该函数在调用时,内部的this指向该对象。如果函数独立调用,那么该函数内部的this,则指向undefined。但是在非严格模式中,当this指向undefined时,它会被自动指向全局对象。
函数
-
函数表达式
-
函数生命
-
匿名函数
-
自执行函数
-
!function(){}()`,`+function(){}()
-
函数传参
实际上结论仍然是按值传递,只不过当我们期望传递一个引用类型时,真正传递的,只是这个引用类型保存在变量对象中的引用而已。
var person = {
name: 'Nicholas',
age: 20
}
function setName(obj) { // 传入一个引用
obj = {}; // 将传入的引用指向另外的值
obj.name = 'Greg'; // 修改引用的name属性
}
setName(person);
console.log(person.name); // Nicholas 未被改变
函数式编程
函数式编程要求,只使用表达式,不使用语句。也就是说,每一步都是单纯的运算,而且都有返回值。
纯函数
只要是同样的参数传入,返回的结果一定是相等的。
函数的隐式转换
当我们没有重新定义toString与valueOf时,函数的隐式转换会调用默认的toString方法,它会将函数的定义内容作为字符串返回。
而当我们主动定义了toString/vauleOf方法时,那么隐式转换的返回结果则由我们自己控制了。
其中valueOf的优先级会toString高一点。
柯里化
柯里化是指这样一个函数(假设叫做createCurry),他接收函数A作为参数,运行后能够返回一个新的函数。并且这个新的函数能够处理函数A的剩余参数。
// 简单实现,参数只能从右到左传递
function createCurry(func, args) {
var arity = func.length;
var args = args || [];
return function() {
var _args = [].slice.call(arguments);
[].push.apply(_args, args);
// 如果参数个数小于最初的func.length,则递归调用,继续收集参数
if (_args.length < arity) {
return createCurry.call(this, func, _args);
}
// 参数收集完毕,则执行func
return func.apply(this, _args);
}
}
做函数的收集。最后统一调用。
总结
js入门的基础知识,也是面试必考的,从基本数据类型的区别、到执行上下的输出,变量对象和活动对象,作用域和作用域链,闭包的概念以及应用。this的指向问题,这些都是我们在面试中必不可少的。