持续更新中o( ̄▽ ̄)ブ
注意:本文所有代码都是在浏览器控制台查看结果的喔!code runner的直接运行结果可能会有所不同喔!
参考资料
https://www.shouce.ren/
词法作用域
JS是一门静态作用域语言。在fn函数中,取自由变量x的值时,要到哪个作用域中取?——要到创建fn函数的那个作用域中取,无论fn函数将在哪里调用。词法作用域也称之为静态作用域,从字面意义上看是说作用域在词法化阶段(通常是指编译阶段)确定而非执行阶段确定。
注意:不要混淆了词法环境和词法作用域,词法作用域是在代码编译阶段确定的作用域(译者注:一个抽象的概念),而词法环境是Javascript引擎用来存储变量和对象引用的地方(译者注:一个具象的概念)。
let number = 42;
function printNumber () {
console.log(number);
}
function log () {
let number = 54;
printNumber();
}
log();
// Prints 42
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
var arr = [];
for (var i = 0; i < 2; i++) {
arr[i] = function () {
console.log(i);
}
}
arr[0]();
arr[1]();
// 2
// 2
let arr = [];
for (let i = 0; i < 2; i++) {
arr[i] = function () {
console.log(i);
}
}
arr[0]();
arr[1]();
// 0
// 1
console.log(f1);
function f1() { }
console.log(f2);
var f2 = function () { }
var a = 10
function fn() {
console.log(a);
}
function bar(f) {
var a = 20
fn()
}
bar(fn)
函数在定义的时候(不是调用的时候),就已经确定了函数体内部自由变量的作用域。
this
指向
构造函数
function Foo() {
this.name = '林见鹿鸣'
this.year = 1000
console.log(this);
}
var f1 = new Foo()
console.log(f1.name);
console.log(f1.year);
function Foo() {
this.name = '林见鹿鸣'
this.year = 1000
console.log(this);
}
Foo()
函数作为对象的属性
var obj = {
x: 10,
fn: function() {
console.log(this);
console.log(this.x);
}
}
obj.fn()
以上代码中,fn不仅作为一个对象的一个属性,而且的确是作为对象的一个属性被调用。结果this就是obj对象。
var obj = {
x: 10,
fn: function() {
console.log(this);
console.log(this.x);
}
}
var fn1 = obj.fn
fn1()
如上代码,如果fn函数被赋值到了另一个变量中,并没有作为obj的一个属性被调用,那么this的值就是window,this.x为undefined。
var n = {
a: 123,
fn: function () {
console.log(a);
}
}
function foo() {
let myName = 456
return n.fn
}
let a = 789
let n2 = foo()
n2()
n.fn()
var n = {
a: 123,
fn: function () {
console.log(this.a);
}
}
function foo() {
let myName = 456
return n.fn
}
let a = 789
let n2 = foo()
n2()
n.fn()
var n = {
a: 123,
fn: function () {
console.log(n.a);
}
}
function foo() {
let myName = 456
return n.fn
}
let a = 789
let n2 = foo()
n2()
n.fn()
var num = 30
const obj1 = {
num: 10,
getNum() {
console.log(this.num);
}
}
const obj2 = {
num: 20
}
obj2.getNum = obj1.getNum
const getNum = obj1.getNum
obj1.getNum()
obj2.getNum()
getNum()
全局 & 普通函数调用
var x = 10
var fn = function() {
console.log(this);
console.log(this.x);
}
fn()
var obj = {
x: 10,
fn: function() {
function f() {
console.log(this);
console.log(this.x);
}
f();
}
};
obj.fn();
原型链
const a = Function instanceof Object
const b = Object instanceof Function
console.log(a,b);
function Foo(){
Foo.a = function(){
console.log(1);
}
this.a = function(){
console.log(2);
}
}
Foo.prototype.a = function(){
console.log(3);
}
Foo.a = function(){
console.log(4);
}
Foo.a(); // 4
let obj = new Foo();
obj.a(); // 2
Foo.a(); // 1
变量提升
foo()
function foo() {
console.log('foo1');
}
foo()
function foo() {
console.log('foo2');
}
foo()
事件循环
for (var i = 1; i <= 4; i++) {
// 立即执行函数不需要调用,立马执行
(function (i) {
setTimeout(() => {
console.log(i)
}, 1000 * i)
})(i)
}
// 下面的代码每隔一秒打印1,2,3,4
for(let i = 1; i <= 4; i++) {
setTimeout(() => {
console.log(i)
}, 1000*i)
}
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');
}, 0)
async1()
console.log('script end');
new Promise((resolve) => {
console.log(0);
resolve(1)
}).then((res) => {
console.log(res);
})
setTimeout(() => {
console.log(2);
})
console.log(3);
综合题型
function test() {
getName = function () {
Promise.resolve().then(() => console.log(0))
console.log(1)
}
return this
}
test.getName = function () {
setTimeout(() => console.log(2), 0)
console.log(3)
}
test.prototype.getName = function () {
console.log(4)
}
var getName = function () {
console.log(5)
}
function getName() {
console.log(6)
}
test.getName()
getName()
test().getName()
getName()
new test.getName()
new test().getName()
new new test().getName()