JavaScript基础课程

第三讲

变量提升

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

  • screenLeft
  • screenTop
  • screenX
  • screenY
  • alert
  • prompt
  • confirm

setTimeout、setInterval

setTimeout:一段时间后执行所给函数

setInterval:每个一段时间执行所给函数

clearTimeout:删除定时器

clearInterval:删除定时器

时间单位是毫秒

function bar() {
    console.log(123);
}
var time = setTimeout(bar, 2000);

clearTimeout(function() {
    console.log(123);
});

//  无效,因为函数是引用 这个和之前的那个不一样了

clearTimeout(time)

//  生效

Location

  • hash
  • host
  • href
  • port
  • assign

Text

  • go
  • back
  • forward