javascript学习笔记略整:
1、for....in对Array的循环得到的是Array的属性,即String,而不是其元素内容。
2、ES6中新增两种数据类型:map/set。map类似于其他语言中的字典类型,而set则是一组key的集合,
1 var m = new map([['Michle',95],['Bob',75],['Tracy',85]]); 2 m.set('Adam',67); //添加新的键值对 3 m.has('Adam'); //是否存在key‘Adam’ 4 m.get('Adam');//67 5 m.delete('Adam');//删除key'Adam' 6 7 var s1 = new set(); //空set 8 var s2 = new set([1,2,3,'3']);//含1,2,3,'3' ,set中不保存相同的key,后二者不相同 9 s1.add(4);//添加key'4' 10 s1.delete(4);//删除key '4'
于是在ES6中引入了新的iterable类型,来统一Array、map、set类型,并通过新的for...of与forEach(func)方法进行遍历调用。
ps:for...in与for...of的区别是for...of只循环遍历元素内容,而非索引(属性)。
1 var a = [1,2,3]; 2 var s = new set(['A','B','C']); 3 var m = new map([[1,'x'],[2,'y'],[3,'z']]); 4 for (var i of a) { //遍历Array数组 5 alert(i); 6 } 7 8 for(var i of s){ //遍历set 9 alert(i); 10 } 11 12 for (var i of m){ 13 alert(i[0] + '=' i[1]); 14 }
forEach:
1 var a = ['A', 'B', 'C']; 2 a.forEach(function (element, index, array) { 3 // element: 指向当前元素的值 4 // index: 指向当前索引 5 // array: 指向Array对象本身 6 alert(element); 7 });
Set
与Array
类似,但Set
没有索引,因此回调函数的前两个参数都是元素本身.
Map
的回调函数参数依次为value
、key
和map
本身:
1 var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]); 2 m.forEach(function (value, key, map) { 3 alert(value); 4 });
问题:函数调用时传入的参数组合arguments是否属于iterable类型???
3、函数的词法作用域表示变量提升??
1 'use strict'; 2 3 function foo() { 4 var x = 'Hello, ' + y; 5 alert(x); //显示Hello,underfined,表明y已经申明,但并未赋值 6 var y = 'Bob'; 7 } 8 9 foo();
由上面的代码效果说明y的申明提前了,但赋值并未提前。
另:函数中有作用域,但表达式中无块作用域,可使用let赋值解决
4、全局作用域的问题:
在javascript语言精粹一书中,曾学到这一概念,
不在任何函数内定义的变量就具有全局作用域。实际上,JavaScript默认有一个全局对象window
,全局作用域的变量实际上被绑定到window
的一个属性:
1 'use strict'; 2 3 var course = 'Learn JavaScript'; 4 alert(course); // 'Learn JavaScript' 5 alert(window.course); // 'Learn JavaScript'
进一步认识到,当函数不是方法调用时,它所传入的this值会绑定到全局变量window上,由此会导致一系列问题.....
为避免全局变量window的影响,减少冲突的一个方法是把自己的所有变量和函数全部绑定到一个全局变量中:
1 // 唯一的全局变量MYAPP: 2 var MYAPP = {}; 3 4 // 其他变量: 5 MYAPP.name = 'myapp'; 6 MYAPP.version = 1.0; 7 8 // 其他函数: 9 MYAPP.foo = function () { 10 return 'foo'; 11 };
至于解决this绑定的问题,有绑定到其他变量然后赋值解决,或者使用apply方法调用
5、高阶函数map、reduce的使用
map是Array的一个高阶方法,用于
1 function pow(x) { 2 return x * x; 3 } 4 5 var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; 6 arr.map(pow); // [1, 4, 9, 16, 25, 36, 49, 64, 81] 7 //相当于给每个Array的元素都带入了pow()函数进行求值
Array的reduce()
把一个函数作用在这个Array
的[x1, x2, x3...]
上,这个函数必须接收两个参数,reduce()
把结果继续和序列的下一个元素做累积计算,其效果就是:
1 [x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)
下面为一例题:我的错误——当时忘了前面的return了
1 'use strict'; 2 3 function product(arr) { 4 return arr.reduce(function(x,y){ 5 return x * y; 6 }); 7 } 8 9 // 测试: 10 if (product([1, 2, 3, 4]) === 24 && product([0, 1, 2]) === 0 && product([99, 88, 77, 66]) === 44274384) { 11 alert('测试通过!'); 12 } 13 else { 14 alert('测试失败!'); 15 }
例:想办法把一个字符串13579
先变成Array
——[1, 3, 5, 7, 9]
,再利用reduce()
就可以写出一个把字符串转换为Number的函数
1 'use strict'; 2 3 function string2int(s) { 4 s.split().map(function(x){ return x -0;}).reduce(function(x,y){ return x *10 + y;}); //split方法将字符串分割为单个字母的数组,而'1'-0的属性为'number' 5 } 6 7 // 测试: 8 if (string2int('0') === 0 && string2int('12345') === 12345 && string2int('12300') === 12300) { 9 if (string2int.toString().indexOf('parseInt') !== -1) { 10 alert('请勿使用parseInt()!'); 11 } else if (string2int.toString().indexOf('Number') !== -1) { 12 alert('请勿使用Number()!'); 13 } else { 14 alert('测试通过!'); 15 } 16 } 17 else { 18 alert('测试失败!'); 19 }
例:请把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。输入:['adam', 'LISA', 'barT']
,输出:['Adam', 'Lisa', 'Bart']