知识体系 就是区分 干活的人 和 创造价值的人的开始
程序是怎么执行的?
-
先进行分词(词法分析)
CString str = "hello"
CString / str / = / "hello"/ -
构建AST(抽象语法树)
- 通过一个json去描述 每一个词是干什么的
- 代码生成
(JIT) JS执行主要分为2个阶段:
- 代码的预编译阶段
- 前置阶段:
- 1.变量声明
- 2.变量提升,但值为undefined
- 3.非表达式函数进行提升
- 前置阶段:
- 代码执行阶段
console.log(a);//undefined
var a = 10;
// => 等效
var a;
console.log(a);
a = 10;
一个变量如何被赋值和使用的,有什么区别?
var a = 2;
1. var a
- 编辑器会先问作用域,是不是已经有了一个a,在当前作用域中了?
+ 是:忽略这个声明,继续往下走
+ 否: 在当前作用域中,生成一个新变量,并命名为 a
2. a = 2
- 编译器会去找是否当前作用域已有a?
+ 是: 赋值为2
+ 否: **回去上一层作用域去找**
var a = 10;
function foo() {
a = 2;
console.log(a);// 2
}
foo();
console.log(a)//2
作用域
- 就是更具名称查找变量的规则
词法作用域(静态作用域)
- 定义在词法阶段作用域(代码写在哪里作用域就在哪里),因此词法分析器处理代码时,会保持代码不变(eval,with除外,不推荐使用)
函数作用域
- 属于函数的全部变量,都可以在整个函数范围使用
上下文
- 词法作用域是在写代码的时候,或者在定义的时候确定的
- 动态作用域(js没有真正的动态作用域),是在运行时确定的
- [高阶函数]
例子1
foo(10);
function foo(num) {
var foo;
console.log(foo);//undefined
foo = num;
console.log(foo);//10
}
console.log(foo);//function
foo = 1;
console.log(foo);//1
this
闭包
- 闭包是一种显现,函数嵌套函数时,内存函数引用了外层函数作用域的变量,并且内层函数在全局作用域下能访问
// => eg1
function fun() {
let num = 1;
return () => {//词法作用域
console.log(num);
}
}
var x = fun();
x();
x();
// => eg2
const foo = (function() {
var v = 0;
return () => v++;
})();
for(let i = 0; i < 10; i++) {
foo();
}
console.log(foo());//10
// => eg3
var fn1;
const fuc = function() {
var a = 2;
function inner() {
console.log(a);
}
fn1 = inner;
}
func();
function bar() {
fn1();
}
bar();//2
this
this指向什么?
this 的指向,是根据上下文,动态决定的
- 在简单调用时, this 默认指向 window/global/undefined (浏览器/node/严格模式)
- 对象调用时,绑定在对象上;
- 使用 call、apply、bind时,绑定在指定的参数上
- 使用 new 关键字,绑定到新建的对象上 (以上优先级 new > apply/call/bind > 对象调用)
- 使用箭头函数,根据外层的规则决定
例子1
const foo = {
bar: 10,
fn: function() {
console.log(this);
console.log(this.bar)
}
}
var fn1 = foo.fn;
fn1();
// this => window this.bar => undefined 浏览器中
// this => global this.bar => undefined node中
foo.fn();// this -> foo this.bar -> 10
例子2
const s = {
name: 'Luck',
fn: function() {
return this;// s
}
}
console.log(s.fn() === s);//true
例子3
const p = {
name: 'lucy',
brother: {
name: 'rr',
fn: function() {
return this.name;
}
}
}
console.log(p.brother.fn());
//this -> p.brother -> rr
例子四
const o1 = {
text: 'o1',
fn: function() {
return this.text
}
}
const o2 = {
text: 'o2',
fn: function() {
return o1.fn();
}
}
const o3 = {
text: 'o3',
fn: function() {
var fn = o1.fn;
return fn();
}
}
console.log(o1.fn());// o1
console.log(o2.fn());// o1
console.log(o3.fn());// undefined
例子5
const foo = {
name: "lucy",
logName: function() {
console.log(this.name);
}
}
const bar = {
name: 'mike'
}
console.log(foo.logName.call(bar));// mike
例子6
var num = 3;
var obj = {
num: 3,
fn: (function() {
var num;
this.num += 2;//10 window
num = 3;
return function() {
var n = this.num;//10 3
this.num *= 2;// 20 6
console.log(n);//3 3
num *= 3;// 9
console.log(num);//9
}
})()
}
var fn = obj.fn;
fn.call(null);// 10 9
obj.fn();//3 27
console.log(window.number);//20