- let var 作用域 作用域链
function foo() {
console.log(this.num)
}
var num = 4;
foo();
// 4
let name = "John";
function sayHi() {
alert("Hi, " + name);
}
name = "Pete";
sayHi();
// pete
function makeWorker() {
let name = "Pete";
return function() {
alert(name);
};
}
let name = "John";
// 创建一个函数
let work = makeWorker();
work();
// Pete
var name = 'Tom';
(function() {
if (typeof name == 'undefined') {
var name = 'Jack';
console.log('Goodbye ' + name);
} else {
console.log('Hello ' + name);
}
})();
// Goodbye Jack
var name = 'Tom';
(function() {
if (typeof name == 'undefined') {
let name = 'Jack';
console.log('Goodbye ' + name);
} else {
console.log('Hello ' + name);
}
})();
// Hello Tom
暂时性死区:
报错的区别
function test1() {
test2()
}
function test2() {
test1()
}
test1() // Uncaught RangeError: Maximum call stack size exceeded
假如不存在提升这个情况,那么就实现不了上述的代码,因为不可能存在 test1 在 test2 前面然后 test2 又在 test1 前面。
let a = function test1() {
test2()
}
let b = function test2() {
test1()
}
a() // Uncaught ReferenceError: test2 is not defined
- this 箭头函数 自行函数 普通函数 对象 构造函数
- 在普通函数下,谁调用这个函数,this指向谁。
- 而箭头函数没有 this,它会从自己的作用域链的上一层继承 this(因此无法使用 apply / call / bind 直接修改 this 值, 可以改变作用域中this的指向可以改变箭头函数的this,eg. function closure(){()=>{//code }},在此例中,我们通过改变封包环境closure.bind(another)(),来改变箭头函数this的指向)。
var name = 'window'
var person1 = {
name: 'person1',
show1: function () {
console.log(this.name)
},
show2: () => console.log(this.name),
show3: function () { //自行函数
return function () {
console.log(this)
}
},
show4: function () {
return () => console.log(this.name)
}
}
var person2 = { name: 'person2' }
person1.show1() // person1,隐式绑定,this指向调用者 person1
person1.show1.call(person2) // person2,显式绑定,this指向 person2
person1.show2() // window,箭头函数绑定,this指向外层作用域,即全局作用域
person1.show2.call(person2) // window,箭头函数绑定,this指向外层作用域,即全局作用域
person1.show3()() // window,默认绑定,这是一个高阶函数,
// 实际调用者是window 如果是严格模式,这里的this就是undefined了
// 类似于`var func = person1.show3()` 执行`func()`
person1.show3().call(person2) // person2,显式绑定,this指向 person2
person1.show3.call(person2)() // window,默认绑定,调用者是window
person1.show4()() // person1,箭头函数绑定,this指向外层作用域,即person1函数作用域
person1.show4().call(person2) // person1,箭头函数绑定,
// this指向外层作用域,即person1函数作用域
person1.show4.call(person2)() // person2
var name = 'window'
function Person (name) {
this.name = name;
this.show1 = function () {
console.log(this.name)
}
this.show2 = () => console.log(this.name)
this.show3 = function () {
return function () {
console.log(this.name)
}
}
this.show4 = function () {
return () => console.log(this.name)
}
}
personA.show1() // personA,隐式绑定,调用者是 personA
personA.show1.call(personB) // personB,显式绑定,调用者是 personB
personA.show2() // personA,首先personA是new绑定,产生了新的构造函数作用域,
// 然后是箭头函数绑定,this指向外层作用域,即personA函数作用域
personA.show2.call(personB) // personA,同上
personA.show3()() // window,默认绑定,调用者是window
personA.show3().call(personB) // personB,显式绑定,调用者是personB
personA.show3.call(personB)() // window,默认绑定,调用者是window
personA.show4()() // personA,箭头函数绑定,this指向外层作用域,即personA函数作用域
personA.show4().call(personB) // personA,箭头函数绑定,call并没有改变外层作用域,
// this指向外层作用域,即personA函数作用域
personA.show4.call(personB)() // personB,解析同题目1,最后是箭头函数绑定,
// this指向外层作用域,即改变后的person2函数作用域
var name = 'in window'
var obj = {
name: "in obj",
getName: function() { return this.name }
}
console.log(obj.getName());
console.log((obj.getName)());
console.log((obj.getName = obj.getName)());
// in obj
// in obj
// in window 相当于react事件没有绑定this当情况
// 即
// this.handleClick = this.handleClick.bind(this);
// button = <LogoutButton onClick={this.handleLogoutClick} />;
- 引用类型 闭包
function Foo() {
var i = 0;
return function () {
console.log(i++);
}
}
var f1 = Foo(),f2 = Foo();
f1(); // 0
f1(); // 1
f2(); // 0
Function是引用类型,保存在堆中,变量f1,f2是保存在栈中
闭包:一个函数(产生新的作用域)定义的局部变量、子函数的作用域在函数内,但是一旦离开了这个函数,局部变量就无法访问,所有通过返回子函数到一个变量f1的方法,让f1指向堆中的函数作用域,这样可以使用局部变量i;f1 = Foo()的时候,创建了一个闭包,并将其作为函数定义的一部分,闭包里的值就是i,当前值为0
过程:
第一次f1(): f1=Foo()中,先执行Foo(): i = 0,return值返回给f1(f1指向子函数 f1()=function(){…},因为子函数没有 定义i,所以向上找到父函数定义的 i: )并执行子函数 输出i=0,再自加 i =1(覆盖了父函数Foo 的 i值);
第二次f1() : 执行的是子函数 Function(){ …},输出的是父函数 的 i=1,再自加 i =2;
第一次f2(): 同第一次f1(),不同的是 f2指向堆中一个新的对象 function(){ …},所有此i非彼i,输出i=0
如果再次f2(),那么和第二次f1(),一样输出i=1;
3.1.
let c = 4
const addX = x => n => n + x
const addThree = addX(3)
let d = addThree(c)
console.log('example partial application', d) // 7
3.2 然后引出一个常见的闭包题目,正确的输出0123…
for (var i = 0; i < 4; i++) {
setTimeout(function() {
console.log(i);
}, 300);
} // 4444
for( var i = 0; i < 4; i ++) {
(function (i) {
setTimeout(function() {
console.log(i);
}, 300);
})(i);
} // 0123 // 自行函数,每次相当于都是一个新的Foo()
for (var i = 0; i < 4; i++) {
setTimeout(
(function() {
console.log(i);
})(i)
, 300);
} // 0123
- js执行顺序
console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
process.nextTick(function() {
console.log('6');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
// 1 7 6 8 2 4 3 5 9 11 10 12
console.log('script start')
async function async1() {
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2 end')
}
async1()
setTimeout(function() {
console.log('setTimeout')
}, 0)
new Promise(resolve => {
console.log('Promise')
resolve()
})
.then(function() {
console.log('promise1')
})
.then(function() {
console.log('promise2')
})
console.log('script end')
// script start => async2 end => Promise => script end => promise1 => promise2 => async1 end => setTimeout
- 引用类型
function test(person) {
person.age = 26
person = {
name: 'yyy',
age: 30
}
return person
}
const p1 = {
name: 'yck',
age: 25
}
const p2 = test(p1)
console.log(p1) // -> ?
console.log(p2) // -> ?

- 两个小坑
var obj = {"key":"1","value":"2"};
var newObj = obj;
newObj.value += obj.key;
console.log(obj.value);
// "21"
浅拷贝 + 字符串和
- 函数
var m = 1, j=k=0;
function add(n){
return n = n+1;
}
y = add(m);
function add(n){
return n = n + 3;
}
z=add(m);
console.log(y + ',' + z);
// 4.4
这是一个函数变量提升的题目
- 类型,隐式转换
String('11') == new String('11');
String('11') === new String('11');
版权声明:本文为yuanfangyoushan原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。