第三讲
console.log(a);
// 报错
console.log(a);
var a = 12;
// undefined
变量提升,就是把变量声明放在了开头,
相当于var a;
console.log(a);
a = 12, 所以是undefined
var a = "hello world";
(function() {
console.log(a);
})();
// hello world
var a = "hello world";
(function() {
console.log(a);
a = 12;
})();
// hello world
var a = "hello world";
(function() {
console.log(a);
var a = "hello";
})();
// undefined
var foo = 10;
function bar() {
if(!foo) {
var foo = 1;
}
console.log(foo);
}
bar();
// 1
// 可以看成如下:
var foo = 10;
function bar() {
var foo;
if(!foo) {
foo = 1;
}
console.log(foo);
}
bar();
我们之前说过,JS里有函数作用域,无块级作用域,所以在函数里,也就是一个新的作用域,我们声明的变量(以及后面要讲的函数)会被提升到作用域开头
var foo = 10;
if(!foo) {
var foo = 1;
}
console.log(foo);
// 10
function bar() {
if(false) {
var x = 1;
}
console.log(x);
}
bar();
// undefined
if(false) {
var y = 1;
}
console.log(y);
// undefined 在全局作用域中变量提升
函数提升
和变量提升类似,在作用域中把函数声明提到最开始
bar();
function bar() {
console.log("hello world");
}
// hello world
bar();
var bar = function() {
console.log("hello world");
}
// 报错
// 等同于如下
var bar;
bar(); // 此时bar是undefined 执行会报错
bar = function() {
console.log("hello world");
}
此时bar被赋值匿名函数
作用域可以向上查找不能向下查找
function bar() {
foo();
console.log(sipc);
function foo() {
var sipc = 12;
}
}
bar();
// 报错
function bar() {
var sipc = 115;
foo();
function foo() {
console.log(sipc);
}
}
bar();
// 115
function bar() {
foo();
var sipc = 115;
function foo() {
console.log(sipc);
}
}
bar();
// undefined
var a = 12;
function bar() {
var a = 11;
foo();
function foo() {
console.log(a);
}
}
bar();
// 11
函数提升比变量提升的优先级高
console.log(sipc);
function sipc(){}
var sipc = 12;
// function sipc(){}
console.log(sipc);
var sipc = 12;
function sipc(){}
// function sipc(){}
bar();
function bar() {
console.log(1);
}
function bar() {
console.log(2);
}
// 2
闭包
var a = [];
for(var i = 0; i < 10; i++) {
a[i] = function() {
console.log(i);
}
}
a[0]();
a[1]();
...
a[9]();
// 10
// 10
// 10
...
// 10
函数的内容为console.log(i);
不是console.log(0/1/2/3/.../9)
此时i又被遍历到了10,
所以结果就输出10
那我们如何让它们输出0123...9呢?
for(var i = 0; i < 10; i++) {
(function() {
console.log(i);
})();
}
// 0
// 1
// 2
...
// 9
我们可以在循环的时候立即执行函数表达式,
这样函数会console.log(i),我们之前又说过
函数作用域是向上查找的,函数找不到i就会向上查找,找到正处于for循环的i变量,就能成功输出123...9了
var a = [];
for(var i = 0; i < 10; i++) {
a[i] = (function(p) {
return function() {
return p;
}
})(i);
}
a[0]() // 0
a[1]() // 1
...
a[9]() // 9
var a = [];
for(var i = 0; i < 10; i++) {
a[i] = (function(i) {
return function() {
return i;
}
})(i);
}
// 一样的结果
我们赋值a[i]为那个return的函数,再调用时会向上查找p/i,又因为我们立即调用了函数表达式,所以每个函数都有一个自己的变量p/i,就可以返回不同的值了,这就是闭包。
闭包其实就是函数可以访问向上函数作用域的变量。
BOM
setTimeout、setInterval
setTimeout:一段时间后执行所给函数
setInterval:每个一段时间执行所给函数
clearTimeout:删除定时器
clearInterval:删除定时器
时间单位是毫秒
function bar() {
console.log(123);
}
var time = setTimeout(bar, 2000);
clearTimeout(function() {
console.log(123);
});
// 无效,因为函数是引用 这个和之前的那个不一样了
clearTimeout(time)
// 生效
Location
Text