栈
者,存储货物或供旅客住宿的地方,可引申为仓库方法名 | 操作 |
---|---|
push() | 添加新元素到栈顶 |
pop() | 移除栈顶的元素,同时返回被移除的元素 |
class Stack {
private items: number[] = [];
// 添加元素到栈顶,也就是栈的末尾
push(element: number) {
this.items.push(element);
}
// 栈的后进先出原则,从栈顶出栈
pop(): number {
return this.items.pop();
}
}
let stack = new Stack();
stack.push(1);
stack.push(2);
stack.push(3);
console.log(stack.pop());
function one() {
function two() {
function three() {
debugger;
}
three();
}
two();
}
one();
function task() {
var a = 1;
var b = 2;
var c = {
name: 'zhufeng',
age: 10
}
}
task();
class Queue {
private items: number[] = [];
// 添加元素到栈顶,也就是栈的末尾
enqueue(element: number) {
this.items.push(element);
}
dequeue() {
return this.items.shift();
}
}
let queue = new Queue();
queue.enqueue(1);
queue.enqueue(2);
queue.enqueue(3);
console.log(queue.dequeue());//1
类型 | 值 |
---|---|
Boolean | true或false |
Null | null |
Undefined | undefined |
Number | 数字 |
String | 字符串 |
Symbol | 符号类型 |
function task(){
var a = 1;
var b = {
name:'zhufeng'
}
var c = [1,2,3];
}
let ExecuteContext = {
VO:{
a:1,
b:'XO1',
c:'XA1'
}
};
var a = 1;
var b = a;
b = 2;
console.log(a);
var ExecuteContext = {
VO: { a: 1 }
};
ExecuteContext.VO.b = ExecuteContext.VO.a;
ExecuteContext.VO.b = 2;
console.log(ExecuteContext.VO.a);
var m = { a: 1, b: 2 };
var n = m;
n.a = 10;
console.log(m.a);
var ExecuteContext = {
VO: { m: { a: 1, b: 2 } }
};
ExecuteContext.VO.b = ExecuteContext.VO.a;
ExecuteContext.VO.a = 10;
console.log(ExecuteContext.VO.a);
function one() {
var a = 1;
debugger;
function two() {
var b = 1;
debugger;
function three() {
var c = 1;
debugger;
}
three();
debugger;
}
two();
debugger;
}
one();
var globalExecuteContext = {
VO: { setTimeout: 'setTimeout' }
}
var executeContextStack = [globalExecuteContext];
var oneExecuteContext = {
VO: { a: 1 }
}
executeContextStack.push(oneExecuteContext);
var twoExecuteContext = {
VO: { b: 2 }
}
executeContextStack.push(twoExecuteContext);
var threeExecuteContext = {
VO: { c: 3 }
}
executeContextStack.push(threeExecuteContext);
console.log(executeContextStack);
executeContextStack.pop();
executeContextStack.pop();
executeContextStack.pop();
this
指向function
进行的函数声明,函数名为变量对象的属性名,值为函数对象,如果属性已经存在,值会用新值覆盖undefined
,如果变量名已经存在,则会跳过,并不会修改原属性值,let
声明的变量并不会在此阶段进行处理var
变量并不会覆盖函数.执行阶段重新赋值可以改变原有的值console.log(a);
var a = 1;
var a = undefined;//变量提升
console.log(a);
a = 1;
var a = 1;
function fn(m) { console.log('fn'); }
function fn(m) { console.log('new_fn'); }
function a() { console.log('fn_a'); }
console.log(a);
fn(1);
var fn = 'var_fn';
console.log(fn);
//1
//new_fn
//var_fn
// 创建阶段
function fn(m) { console.log('fn'); }
function fn(m) { console.log('new_fn'); }
function a() { console.log('fn_a'); }
var a = undefined;
var fn = undefined;
//执行阶段
a = 1;
console.log(a);
fn();
fn = 'var_fn';
console.log(fn);
// 创建阶段
var globalEC = {
VO: {
...arguments,
a: () => { console.log('fn_a'); },
fn: () => { console.log('new_fn'); }
}
}
var ECStack = [globalEC];
//执行阶段
globalEC.VO.a = 1;
console.log(globalEC.VO.a);
globalEC.VO.fn();
globalEC.VO.fn = 'var_fn';
console.log(globalEC.VO.fn);
this
指针function one(m) {
function two() {
console.log('two');
}
}
one(1);
//执行阶段 VO=>AO
let VO = AO = {
m:1,
two: () => { console.log('two'); },
}
let oneEC={
VO,
this: window,
scopeChain:[VO,globalVO]
}
window
window
,而且这个变量对象不能激活变成活动对象function one() {
var a = 1;
}
console.log(a);
function one() {
var a = 1;
function two() {
var b = 2;
function three() {
var c = 3;
console.log(a, b, c);
}
three();
}
two();
}
one();
// 1.创建全局上下文
var globalExecuteContextVO = { one: `()=>{var a = 1;}` }
var globalExecuteContext = {
VO: globalExecuteContextVO,
scopeChain: [globalExecuteContextVO]
}
var executeContextStack = [globalExecuteContext];
//2.执行one,创建one执行上下文
var oneExecuteContextVO = {
a: 1,
two: `()=>{var b = 2 ;}`
}
var oneExecuteContext = {
VO: oneExecuteContextVO,
scopeChain: [oneExecuteContextVO, globalExecuteContext.VO]
}
//2.执行two,创建two执行上下文
var twoExecuteContextVO = {
b: 2,
three: `()=>{var c = 3 ;}`
}
var twoExecuteContext = {
VO: twoExecuteContextVO,
scopeChain: [twoExecuteContextVO, oneExecuteContext.VO, globalExecuteContext.VO]
}
//3.执行three,创建three执行上下文
var threeExecuteContextVO = {
c: 3
}
var threeExecuteContext = {
VO: threeExecuteContextVO,
scopeChain: [threeExecuteContextVO, twoExecuteContext.VO, oneExecuteContext.VO, globalExecuteContext.VO]
}
function getValue(varName) {
for (let i = 0; i < threeExecuteContext.scopeChain.length; i++) {
if (varName in threeExecuteContext.scopeChain[i]) {
return threeExecuteContext.scopeChain[i][varName];
}
}
}
//console.log(a, b, c);
console.log(
getValue('a'),
getValue('b'),
getValue('c'),
);
scopeChain
其实是在创建函数的时候确定的function one() {
var a = 1;
function two() {
console.log(a);
}
return two;
}
var a = 2;
var two = one();
two();
// 1.创建全局上下文
var globalExecuteContextVO = { one: `()=>{var a = 1;}`, a: undefined, two: undefined }
var globalExecuteContext = {
VO: globalExecuteContextVO,
scopeChain: [globalExecuteContextVO]
}
//2.开始执行
globalExecuteContextVO.a = 2;
//3.开始执行one
var oneExecuteContextVO = { a: undefined, two: `()=>{console.log(a)}` }
var oneExecuteContext = {
VO: oneExecuteContextVO,
scopeChain: [oneExecuteContextVO, globalExecuteContextVO]
}
oneExecuteContextVO.a = 1;
//4.给two赋值
globalExecuteContextVO.two = oneExecuteContextVO.two;
//5.执行two
var twoExecuteContextVO = {}
var twoExecuteContext = {
VO: twoExecuteContextVO,
//scopeChain是在创建此函数据的时候就决定了,跟在哪里执行无关
scopeChain: [twoExecuteContextVO, oneExecuteContextVO, globalExecuteContextVO]
}
foo
,它包含了一个函数fn
,这个函数fn1
可以调用被这个作用域所封闭的变量a
、函数等内容Call Stack
为当前的函数调用栈Scope
为当前正在被执行函数的作用域链 Local
为当前的活动对象function one() {
var a = 1;
var b = 2;
function two() {
var c = 3;
debugger;
console.log(a,c);
}
return two;
}
let two = one();
two();
function one() {
var a = 1;
var b = 2;
function two() {
debugger;
console.log(a);
}
two();
}
one();
function one() {
var a = 1;
function two() {
var b = 2;
function three() {
var c = 3;
debugger;
console.log(a, b, c);
}
three();
}
two();
}
one();
function one() {
var a = 1;
function two() {
var b = 2;
function three() {
var c = 3;
debugger;
console.log(a, c);
}
three();
}
two();
}
one();
function log(a, b) {
debugger;
console.log(a, b);
}
log(1, 2);
{ }
包括,if
语句和for
语句里面的{ }
也属于块作用域for(var i=0;i<=5;i++){
console.log("hello");
}
console.log(i); //5
var a = 1;
function fn() {
console.log(a);
if (false) {
var a = 2;
}
}
fn(); //undefined
'use strict'
function fn() {
console.log("out");
}
(function () {
if (false) {
function fn() {
console.log("in");
}
}
fn();
}());
let
会在编译阶段报错// 不存在变量提升
'use strict';
function func(){
console.log(i);
let i;
};
func(); // 报错
'use strict'
var a = 1;
console.log(a);//1
{
console.log(a);// f 1
function a() {
console.log(1);
}
}
console.log(a);// f 1
var a=1;//声明绑定变量对象,但在全局环境中,变量对象就是全局对象
this.b=2;//this绑定全局对象
c=3;//赋值操作 隐式绑定
this
就是谁let obj = {
getName(){
console.log(this);
}
};
obj.getName();
let obj = {
getName(){
console.log(this);
}
};
let getName = obj.getName;
getName();
container.addEventListener('click',function(){
console.log(this);
});
let fn = () => {
console.log(this);
console.log(arguments);//Uncaught ReferenceError: arguments is not defined
}
console.log(fn.prototype);//undefined
fn();
new fn();//VM4416:8 Uncaught TypeError: fn is not a constructor
function fn(){
}
let obj = new fn();
!function (proto) {
function getContext(context) {
context = context || window;
var type = typeof context;
if (['number', 'string', 'boolean', 'null'].includes(type)) {
context = new context.constructor(context);
}
return context;
}
function call(context, ...args) {
context = getContext(context);
context._fn = this;
let result = context._fn(...args);
delete context._fn;
return result;
}
function apply(context, args) {
context = getContext(context);
context._fn = this;
let result = context._fn(...args);
delete context._fn;
return result;
}
function bind(context, ...bindArgs) {
return (...args) => this.call(context, ...bindArgs, ...args);
}
proto.call = call;
proto.apply = apply;
proto.bind = bind;
}(Function.prototype)
隐式 > 默认
function one() {
console.log(this)
}
var obj = {
name: "obj",
one
}
obj.one()
显示 > 隐式
function one() {
console.log(this)
}
var obj = {
name: "obj",
one: one.bind("hello")
}
obj.one()
new > 显示
function one() {
console.log(this)
}
var helloOne = one.bind("hello")
var obj = new helloOne();
console.log(obj);
typeof function='function'
typeof
返回的都是字符串console.log(typeof a); // undefined
console.log(typeof 1); // number
console.log(typeof 'zhufeng'); // string
console.log(typeof true); // boolean
console.log(typeof Symbol('a')); // symbol
console.log(typeof function () { }); //function
console.log(typeof [1, 2, 3]); //object
console.log(typeof { name: 'zhufeng' }); //object
console.log(typeof null); //object
console.log(typeof new Number(1)); //object
Object
let obj = new Object();
obj.name='zhufeng';
obj.age = 10;
__proto__
指向的是null
prototype
的proto指向的就是Object.prototypeFunction.prototype
let add = new Function('a','b','return a+b');
console.log(add(1,2));
__proto__
这条链来向上查找找,如果能找到函数的prototype则返回true,否则 返回falsenew
来调用一个函数,这个函数就成为了构造函数,构造函数里可以对例对象的私有属性赋值prototype
属性,此原型对象上存放所有实例的公有方法function Person(name) {
this.name = name;
}
Person.prototype.getName = function () {
console.log(this.name);
}
let person = new Person('zhufeng');
person.getName();
Object.create = function (proto) {
function F() {}
F.prototype = proto;
return new F();
};
function _new(clazz, ...args) {
let _this = Object.create(clazz.prototype);
let result = clazz.call(_this, ...args);
if ((result != null && typeof result === 'object') || typeof result === 'function') {
return result;
}
return _this;
}
class Father {
static staticFatherName = "FatherName"
static staticGetFatherName = function () {
console.log(Father.staticFatherName);
}
constructor(public name) {
this.name = name;
}
getName() {
console.log(this.name);
}
}
class Child extends Father {
static staticChildName = "ChildName"
static staticGetChildName = function () {
console.log(Child.staticChildName);
}
constructor(public name, public age) {
super(name);
this.age = age;
}
getAge() {
console.log(this.age);
}
}
let child = new Child('zhufeng', 10);
child.getName();
child.getAge();
Child.staticGetFatherName();
Child.staticGetChildName();
var _extends = (function () {
var extendStatics = function (Child, Father) {
return Object.setPrototypeOf(Child, Father);
}
return function (Child, Father) {
extendStatics(Child, Father);
function Temp() {
this.constructor = Child;
}
Temp.prototype = Father.prototype;
Child.prototype = new Temp();
};
})();
var Father = (function () {
function Father(name) {
this.name = name;
}
Father.prototype.getName = function () {
console.log(this.name);
};
Father.staticFatherName = "FatherName";
Father.staticGetFatherName = function () {
console.log(Father.staticFatherName);
};
return Father;
}());
//_super父类构造函数
var Child = (function (_super) {
_extends(Child, _super);
function Child(name, age) {
_super.call(this, name);//继承父类的实例私有属性
this.age = age;
return this;
}
Child.prototype.getAge = function () {
console.log(this.age);
};
Child.staticChildName = "ChildName";
Child.staticGetChildName = function () {
console.log(Child.staticChildName);
};
return Child;
}(Father));
let child = new Child('zhufeng', 10);
console.log(child);
child.getName();
child.getAge();
Child.staticGetFatherName();
Child.staticGetChildName();
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var Father = /** @class */ (function () {
function Father(name) {
this.name = name;
this.name = name;
}
Father.prototype.getName = function () {
console.log(this.name);
};
Father.staticFatherName = "FatherName";
Father.staticGetFatherName = function () {
console.log(Father.staticFatherName);
};
return Father;
}());
var Child = /** @class */ (function (_super) {
__extends(Child, _super);
function Child(name, age) {
var _this = _super.call(this, name) || this;
_this.name = name;
_this.age = age;
_this.age = age;
return _this;
}
Child.prototype.getAge = function () {
console.log(this.age);
};
Child.staticChildName = "ChildName";
Child.staticGetChildName = function () {
console.log(Child.staticChildName);
};
return Child;
}(Father));
var child = new Child('zhufeng', 10);
child.getName();
child.getAge();
Child.staticGetFatherName();
Child.staticGetChildName();
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();
getName();
Foo().getName();
getName();//1
new Foo.getName();
new Foo().getName();
new new Foo().getName();
// 2 4 1 1 2 3 3
async function async1() {
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2')
}
console.log('script start')
setTimeout(function () {
console.log('setTimeout')
})
async1()
new Promise(function (resolve) {
console.log('promise1')
resolve()
}).then(function () {
console.log('promise2')
})
console.log('script end')
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout
function fn() {
var a = 1;
let b = 2;
{
let b = 3;
var c = 4;
let d = 5;
//console.log(a, b, c, d);//TODO
}
{
let b = 6;
let d = 7;
//console.log(a, b, c, d);
}
}
fn();
/**
* 1.global编译阶段
*/
let globalEC = {
this: globalThis,
outer: null,//外部的执行上下文,词法作用域就是静态作用域,就是指作用域是由代码中函数声明的位置来决定的
variableEnvironment: {
fn() { console.log(a, b, c, d) }
},
lexicalEnvironment: {}
}
/**
* 2.fn编译阶段
*/
let fnEC = {
this: globalThis,
outer: globalEC,
variableEnvironment: { a: undefined, c: undefined },
lexicalEnvironment: [{ b: undefined }]
}
/**
* 3.编译代码块1
*/
fnEC.variableEnvironment.a = 1;
fnEC.lexicalEnvironment.b = 2;
fnEC.lexicalEnvironment.push({
b: undefined,
d: undefined
});
/**
* 4.执行代码块1
*/
fnEC.lexicalEnvironment[1].b = 3;
fnEC.variableEnvironment.c = 4;
fnEC.lexicalEnvironment[1].d = 5;
console.log(getValue('a', fnEC), getValue('b', fnEC), getValue('c', fnEC), getValue('d', fnEC));
function getValue(name, ec) {
for (let i = ec.lexicalEnvironment.length - 1; i >= 0; i--) {
if (name in ec.lexicalEnvironment[i]) {
return ec.lexicalEnvironment[i][name];
}
}
let currentVariableEnvironment = ec.variableEnvironment;
while (currentVariableEnvironment) {
if (name in currentVariableEnvironment) {
return currentVariableEnvironment[name];
}
currentVariableEnvironment = currentVariableEnvironment.outer;
}
return null;
}
/**
* 5.编译代码块2
*/
fnEC.lexicalEnvironment.pop();
fnEC.lexicalEnvironment.push({
b: undefined,
d: undefined
});
/**
* 5.执行代码块2
*/
fnEC.lexicalEnvironment[1].b = 6;
fnEC.lexicalEnvironment[1].d = 7;
console.log(getValue('a', fnEC), getValue('b', fnEC), getValue('c', fnEC), getValue('d', fnEC));
/* let name = 'zhufeng'
{
//ReferenceError: Cannot access 'name' before initialization
console.log(name)
let name = 'jiagou'
} */
function two() {
console.log(a);
}
function one() {
var a = 2;
two();
}
var a = 1;
one();
let globalEC = {
a: 1,
one() { },
two() { }
}
let twoEC = {
this: globalThis,
outer: globalEC,
variableEnvironment: { a: 1, two() { console.log(a) } } //出生的地方
}
var twoEc = { outer: globalEC };
console.log(twoEC.outer.a);
function one() {
var a = 1;
var name = 'one';
function two() {
var b = 2;
var name = 'two';
function three() {
var c = 3;
var name = 'three';
return () => console.log(a, b, c);
}
return three();
}
return two();
}
var fn = one();
fn();
let globalEC = {
this: globalThis,
outer: null,
variableEnvironment: { one() { } }
}
let oneEC = {
this: globalThis,
outer: globalEC.variableEnvironment,
variableEnvironment: { a: 1, two() { }, name: 'one' }
}
let twoEC = {
this: globalThis,
outer: oneEC.variableEnvironment,
variableEnvironment: { b: 2, three() { }, name: 'two' }
}
let threeEC = {
this: globalThis,
outer: twoEC.variableEnvironment,
variableEnvironment: { c: 3, name: 'three' }
}
let fnEC = {
this: globalThis,
outer: globalEC,
//Closure(three) Closure(two) Closure(one)
closures: [{ a: 1 }, { b: 2 }, { c: 3 }],
variableEnvironment: { c: 3 }
}
console.log(getValue('a', fnEC), getValue('b', fnEC), getValue('c', fnEC));
function getValue(name, ec) {
for (let i = ec.closures.length - 1; i >= 0; i--) {
if (name in ec.closures[i]) {
return ec.closures[i][name];
}
}
let currentVariableEnvironment = ec.variableEnvironment;
while (currentVariableEnvironment) {
if (name in currentVariableEnvironment) {
return currentVariableEnvironment[name];
}
currentVariableEnvironment = currentVariableEnvironment.outer;
}
return null;
}