JavaScript采用的是静态作用域
因为 JavaScript 采用的是词法作用域,函数的作用域在函数定义的时候就决定了。
而与词法作用域相对的是动态作用域,函数的作用域是在函数调用的时候才决定的。
var value = 1;
function foo() {
console.log(value);
}
function bar() {
var value = 2;
foo();
}
bar();
// 结果是 1
假设JavaScript采用静态作用域,让我们分析下执行过程:
执行 foo 函数,先从 foo 函数内部查找是否有局部变量 value,如果没有,就根据书写的位置,查找上面一层的代码,也就是 value 等于 1,所以结果会打印 1。
假设JavaScript采用动态作用域,让我们分析下执行过程:
执行 foo 函数,依然是从 foo 函数内部查找是否有局部变量 value。如果没有,就从调用函数的作用域,也就是 bar 函数内部查找 value 变量,所以结果会打印 2。
前面我们已经说了,JavaScript采用的是静态作用域,所以这个例子的结果是 1。
// es6之前 全局作用域:整个script标签,或者是一个单独的js文件 /局部作用域,函数内部
//块级作用域{}
//作用域链:内部函数访问外部函数的变量,采取的是链式查找的方式来决定是那个值(就近原则)
//js引擎运行js分为两步:预解析 代码执行
//预解析 js引擎会把js里面所有的var还有function提升到当前作用域最前面
//变量预解析(变量提升)变量声明提升到当前作用域最前面 不提升赋值操作
//console.log(num);var num=10;---->undefined
<!--多选框多选与取消多选实例-->
如果 % 左边的操作数是负数,则模除的结果为负数或零。
1、字符串一个很能强大的数据类型;在执行加 + 时,将被加的对象统一处理为字符串。
2、bool 类型在与数字类型进行相加时,视为 0 或者 1 处理。
3、null 类型与数字类型进行累加时,视为 0 处理。
4、bool 类型与 null 类型进行累加时,视为其与整数类型累加处理。
5、undefined 除了与字符串进行累加时有效(undefined 视为字符串"undefined"处理),其他情况皆返回 NaN。
循环一个 DOM collection
循环一个DOM collections,比如NodeList,之前我们讨论过如何循环一个NodeList,现在方便了,可以直接使用for-of循环:
// Note: This will only work in platforms that have
// implemented NodeList.prototype[Symbol.iterator]
let articleParagraphs = document.querySelectorAll("article > p");
for (let paragraph of articleParagraphs) {
paragraph.classList.add("read");
}
循环一个拥有enumerable属性的对象
for–of循环并不能直接使用在普通的对象上,但如果我们按对象所拥有的属性进行循环,可使用内置的Object.keys()方法:
for (var key of Object.keys(someObject)) {
console.log(key + ": " + someObject[key]);
}
循环一个生成器(generators)
我们可循环一个生成器(generators):
function* fibonacci() { // a generator function
let [prev, curr] = [0, 1];
while (true) {
[prev, curr] = [curr, prev + curr];
yield curr;
}
}
for (let n of fibonacci()) {
console.log(n);
// truncate the sequence at 1000
if (n >= 1000) {
break;
}
}
定义了数组后对数组进行赋值,中间如有某些下标未被使用(即未被赋值),在遍历的时候,采用一般的 for 循环和 for…in 循环得到的结果不同。
for…in 循环会自动跳过那些没被赋值的元素,而 for 循环则不会,它会显示出 undefined。
<button onclick="myFunction()">点击这里</button>
<p id="demo"></p>
<script>
function myFunction(){
var array = new Array();
var x;
var txt=""
array[0] = 1;
array[3] = 2;
array[4] = 3;
array[10] = 4;
for( x in array ){
alert(array[x]); // 依次显示出 1 2 3 4
}
alert(array.length); // 结果是11
for( var i=0 ; i<4 ; i++){
alert(array[i]); // 依次显示出 1 undefined undefined 2
}
document.getElementById("demo").innerHTML = txt;
}
</script>
for : 比较适合遍历数组,字符串等等。
for in : 比较适合遍历对象,遍历对象时使用这个再合适不过了。
while : while 的话,与 for 的使用场景差不多。唯一不同的是,遍历的条件必须满足。
do while : 至少执行一边的循环,遍历数组和字符串也是很方便。
while遍历数组的例子中,如果数组中有 0,null,false,undefined 或者空字符串等在 js 中被认为等价于 false 的值,会提前结束遍历。
while (i < cars.length) 而不要使用while (cars[i])
关于 JavaScript 标签与 break 和 continue 一起使用的理解
//break 的作用是跳出代码块, 所以 break 可以使用于循环和 switch 等
//continue 的作用是进入下一个迭代, 所以 continue 只能用于循环的代码块,代码块: 基本上是{}大括号之间
//默认标签的情况(除了默认标签情况,其他时候必须要有名标签,当 break 和 continue 同时用于循环时,没有加标签,此时默认标签为当前"循环"的代码块,当 break 用于 switch 时,默认标签为当前的 switch 代码块:
//有名标签的情况
cars=["BMW","Volvo","Saab","Ford"];
list:
{
document.write(cars[0] + "");
document.write(cars[1] + "");
document.write(cars[2] + "");
break list;
document.write(cars[3] + "");
document.write(cars[4] + "");
document.write(cars[5] + "");
}
//上述break list;会跳出list的代码块。如果将break换成continue会有惊喜,违反了明确中的第二点,因为list只是个普通代码块,而不是循环。除非list写成如下形式 list:
for(var i=0; i<10; ++i)
{
continue list;
}
//有了标签,可以使用break和continue在多层循环的时候控制外层循环。
outerloop:
for (var i = 0; i < 10; i++)
{
innerloop:
for (var j = 0; j < 10; j++)
{
if (j > 3)
{
break;
}
if (i == 2)
{
break innerloop;
}
if (i == 4)
{
break outerloop;
}
document.write("i=" + i + " j=" + j + "");
}
}
数据类型
undefined:是所有没有赋值变量的默认值,自动赋值。
null:主动释放一个变量引用的对象,表示一个变量不再指向任何对象地址。
何时使用null?
当使用完一个比较大的对象时,需要对其进行释放内存时,设置为 null。
null 与 undefined 的异同点是什么呢?
共同点:都是原始类型,保存在栈中变量本地。
不同点:
typeof undefined // undefined
typeof null // object
(1)undefined——表示变量声明过但并未赋过值。
它是所有未赋值变量默认值,例如:
var a; // a 自动被赋值为 undefined
(2)null——表示一个变量将来可能指向一个对象。
一般用于主动释放指向对象的引用,例如:
var emps = [‘ss’,‘nn’];
emps = null; // 释放指向数组的引用
NaN 的数据类型是 number
数组(Array)的数据类型是 object
日期(Date)的数据类型为 object
null 的数据类型是 object
未定义变量的数据类型为 undefined
如果对象是 JavaScript Array 或 JavaScript Date ,我们就无法通过 typeof 来判断他们的类型,因为都是 返回 object。
constructor 属性来查看对象是否为数组 (包含字符串 “Array”)
var fruits = ["Banana", "Orange", "Apple", "Mango"];
document.getElementById("demo").innerHTML = isArray(fruits);
function isArray(myArray) {
return myArray.constructor.toString().indexOf("Array") > -1;
}