当前位置: 代码迷 >> 综合 >> javaScripts(一)
  详细解决方案

javaScripts(一)

热度:33   发布时间:2023-11-17 11:20:11.0

一、基础语法

1、定义变量var a=54
2、输出变量console.log(a)
3、条件判断if (2 > 1) {x = 1;y = 2;z = 3;if (x < y) {z = 4;}if (x > y) {z = 5;}
}4、注释  //   /*...*/

二、数据类型和字符串

1、number
JavaScript不区分整数和浮点数,统一用Number表示,以下都是Number类型123; // 整数1230.456; // 浮点数0.4561.2345e3; // 科学计数法表示1.2345x1000,等同于1234.5-99; // 负数NaN; // NaN表示Not a Number,当无法计算结果时用NaN表示Infinity; // Infinity表示无限大,当数值超过了JavaScript的Number所能表示的最大值时,就表示为Infinity2、字符串 布尔值  比较运算符和python类似
例外:
第一种是==比较,它会自动转换数据类型再比较,很多时候,会得到非常诡异的结果;
第二种是===比较,它不会自动转换数据类型,如果数据类型不一致,返回false,如果一致,再比较。
由于JavaScript这个设计缺陷,不要使用==比较,始终坚持使用===比较。判断NaN的函数:isNaN(NaN)3、未定义 undefined     null空4、创建数组第一种方法:[1, 2, 3.14, 'Hello', null, true];第二种方法:new Array(1, 2, 3);//创建了[1,2,3]5、对象由一组键值对组成的无序集合,键必须是字符串类型
var person = {name: 'Bob',age: 20,tags: ['js', 'web', 'mobile'],city: 'shenzhen',hasCar: true,zipcode: null
};
JavaScript对象的键都是字符串类型,值可以是任意数据类型。上述person对象一共定义了6个键值对,其中每个键又称为对象的属性,例如,person的name属性为'Bob',zipcode属性为null获取对象的属性的方法
person.name6、在JavaScript中,使用等号=对变量进行赋值。可以把任意数据类型赋值给变量,同一个变量可以反复赋值,而且可以是不同类型的变量,但是要注意只能用var申明一次例如:
var a = 123; // a的值是整数123
a = 'ABC'; // a变为字符串7、模板字符串var name = '小明';var age = 20;var message = `你好, ${name}, 你今年${age}岁了!`;#**注意字符串两端的字符  【返单引号】**alert(message);
8、操作字符串var s = 'Hello, world!';s.length; // 13var s = 'Hello, world!';s[0]; // 'H's[6]; // ' 's[7]; // 'w's[12]; // '!'s[13]; // undefined 超出范围的索引不会报错,但一律返回undefined9、需要特别注意的是,字符串是不可变的,如果对字符串的某个索引赋值,不会有任何错误,但是,也没有任何效果:var s = 'Test';
s[0] = 'X';
alert(s); // s仍然为'Test'10、toUpperCase()全部大写var a='helloworld'a.toUpperCase()//HELLOWORLD11、toLowerCase()//全部小写var a='HELLOWORLD'a.LowerCase()//helloworld12、indexOf()//返回指定字符串出现的位置的索引var a='helloworld'a.indexOf('world')//5
13、substring()//返回指定索引区间的字串var a='helloworld'a.substring(0,5)//hello

三、数组

1、JavaScript的Array可以包含任意数据类型,并通过索引来访问每个元素
var arr = [1, 2, 3.14, 'Hello', null, true];
arr.length; // 6请注意,直接给Array的length赋一个新的值会导致Array大小的变化var arr = [1, 2, 3];
arr.length; // 3
arr.length = 6;
arr; // arr变为[1, 2, 3, undefined, undefined, undefined]
arr.length = 2;
arr; // arr变为[1, 2]修改:
var arr = [1, 2, 3];
arr[5]=55
arr; // arr变为[1, 2, 3, undefined, undefined, 'x']2、indexOf()  #搜索一个指定的元素的位置var arr = [10, 20, '30', 'xyz'];
arr.indexOf(10); // 元素10的索引为0
arr.indexOf(20); // 元素20的索引为1
arr.indexOf(30); // 元素30没有找到,返回-1
arr.indexOf('30'); // 元素'30'的索引为23、slice() 截取部分元素var arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
arr.slice(0, 3); // 从索引0开始,到索引3结束,但不包括索引3: ['A', 'B', 'C']
arr.slice(3); // 从索引3开始到结束: ['D', 'E', 'F', 'G']注意:如果不给slice()传递任何参数,它就会从头到尾截取所有元素。利用这一点,我们可以很容易地复制一个Array4、push和pop
push()向Array的末尾添加若干元素,pop()则把Array的最后一个元素删除var a=[1,2,3]
a.push(4,5)
a//[1,2,3,4,5]
a.pop()// 5
a.pop() a.pop() a.pop()
a//[]
a.pop()//不会报错而是会返回undefined5、unshift和shift
unshirt//往头部增加元素      shirt删除头部第一个元素
var a=[1,2,3,4]
a.unshirt(55)//往头部增加元素 返回对象a的长度
a.shirt()//删除头部第一个元素,返回删除的元素
a.shift(); arr.shift(); arr.shift();arr.shift(); // 连续shift 4次
a//[]
a.shift(); // 空数组继续shift不会报错,而是返回undefined6、sort排序
sort()可以对当前Array进行排序,它会直接修改当前Array的元素位置,直接调用时,按照默认顺序排序:var arr = ['B', 'C', 'A'];
arr.sort();
arr; // ['A', 'B', 'C']7、reverse反转
var a=[1,2,3]
a.reverse()
a//[3,2,1]8、splice
splice()方法是修改Array的“万能方法”,它可以从指定的索引开始删除若干元素,然后再从该位置添加若干元素:
var s=[1,2,3]
#从索引1开始删除3个元素 并增加两个元素
s.splice(1,3,'hello','world')  //返回删除的元素3
s//[1,'hello','world']
#只增加不删除
s.splice(2,0,99,88)///[1,'hello','world',99,88]
#只删除不增加
ssplice(2,10)//返回删除的元素,超出索引范围不报错
9、concat
concat()方法把当前的Array和另一个Array连接起来,并返回一个新的Array
var a=[1,2,3]
var s=a.concat(10,20)//[1,2,3,10,20]
a//[1,2,3]
请注意,concat()方法并没有修改当前Array,而是返回了一个新的Array。
实际上,concat()方法可以接收任意个元素和Array,并且自动把Array拆开,然后全部添加到新的Array里:
var s=[1,2,3]
var b=s.concat([4,5],6)//[1,2,3,4,5,6]
10、join
var a=[1,2,3]
a.join('*')//返回 “1*2*3”,先自动转换成字符串在连接

四、对象

 1、定义对象的格式var xiaoming = {name: '小明',birth: 1990,school: 'No.1 Middle School',height: 1.70,weight: 65,score: null};获取对象:xiaoming.name//小明假设属性包含特殊字符:var xiaohong = {name: '小红','middle-school': 'No.1 Middle School'};必须在获取属性的字段加上‘’引号才可以获取xiaohong['middle-school']//因为middle-school不是有效的变量所以必须以这个格式访问, 'No.1 Middle School'2、给对象添加或者删除属性var xiaoming = {name: '小明'};xiaoming.age; // undefinedxiaoming.age = 18; // 新增一个age属性xiaoming.age; // 18delete xiaoming.age; // 删除age属性xiaoming.age; // undefineddelete xiaoming['name']; // 删除name属性xiaoming.name; // undefineddelete xiaoming.school; // 删除一个不存在的school属性也不会报错判断某一对象是否拥有此属性用 'in'格式:'name' in xiaoming; // true如果返回结果为true  则不一定是拥有的,有可能的继承的
判断是否自己本身拥有的属性 对象.hasOwnProperty('属性名')var xiaoming = {name: '小明'};xiaoming.hasOwnProperty('name'); // true  本身拥有xiaoming.hasOwnProperty('toString'); // false

五、条件判断

   	```1、条件判断格式:**if () { ... } else { ... }**var age = 20;if (age >= 18) { // 如果age >= 18为true,则执行if语句块alert('adult');} else { // 否则执行else语句块alert('teenager');}条件判断else后面不能省略{..} 否则会出现不可预料的问题 var age = 20;if (age >= 18)alert('adult');elseconsole.log('age < 18'); // 添加一行日志alert('teenager'); // <- 这行语句已经不在else的控制范围了相反地,有{}的语句就不会出错:var age = 20;if (age >= 18) {alert('adult');} else {console.log('age < 18');alert('teenager');}
**2、多条件判断**  if ... else if....var age = 3;if (age >= 18) {alert('adult');} else if (age >= 6) {alert('teenager');} else {alert('kid');}实际相当于嵌套了一层var age = 3;if (age >= 18) {alert('adult');} else {if (age >= 6) {alert('teenager');} else {alert('kid');}}javascripts把null、undefined、0、NaN和空字符串''视为false

六、循环

1、**格式(类似java的for循环)**var x = 1;var i;for (i=1;i<=10;i++){x=x*i;}条件分析:i=1 这是初始条件,将变量i置为1;i<=10 这是判断条件,满足时就继续循环,不满足就退出循环;i++ 这是每次循环后的递增条件,由于每次循环后变量i都会加1,因此它终将在若干次循环后不满 足判断条件i<=10而退出循环。特别注意:每个变量后面必须以   ;号结尾2、**循环的条件是可以省略的**var x = 0;for (;;) { // 将无限循环下去if (x > 100) {break; // 通过if判断来退出循环}x ++;}
3、for......invar o = {name: 'Jack',age: 20,city: 'shenzhen'};for (var key in o) {if (o.hasOwnProperty(key ))//如果属性不是继承的console.log(key); // 'name', 'age', 'city'}
请注意,for....in对Array循环得到的是string而不是number由于Array也是对象,而它的每个元素的索引被视为对象的属性,因此,for ... in循环可以直接循环出Array的索引:var a = ['A', 'B', 'C'];for (var i in a) {console.log(i); // '0', '1', '2'console.log(a[i]); // 'A', 'B', 'C'}for... of...循环出的是元素:var a = ['A', 'B', 'C'];for (var i of a) {console.log(i); // 'A', 'B', 'C'}4、while循环var x = 0;var n = 99;while (n > 0) {x = x + n;n = n - 2;}x; // 25005、do....while//循环结束判断条件**~~它和while循环的唯一区别在于,不是在每次循环开始的时候判断条件,而是在每次循环完成的时候判断条件~~ **var n = 0;do {n = n + 1;} while (n < 100);n; // 100循环结束判断是否满足条件,满足继续执行,不满足退出

七、Map和Set

1、Mapvar m=new Map([['name','刘德华'],['age',12],['addr','深圳']])//键必须是字符串m.get('name')**初始化Map需要一个二维数组,或者直接初始化一个空Map** Map的方法var m = new Map(); // 初始化空Mapm.set('Adam', 67); // 添加新的key-valuem.set('Bob', 59);m.has('Adam'); // 是否存在key 'Adam': truem.get('Adam'); // 67m.delete('Adam'); // 删除key 'Adam'm.get('Adam'); // undefined由于一个key只能对应一个value,所以后面设置的value会覆盖前面设置的值var m = new Map();m.set('Adam', 67);m.set('Adam', 88);//重复赋值,覆盖前面的值m.get('Adam'); // 882、Set  **对象.add(值) 添加**             **对象.delete(值)  删除**var s= new Set([1,2,3,4,5])s.add(9)s//{1,2,3,4,5,9}s.delete(4)s//{1,2,3,5,9}

八、iterable

1、Map  Set  Array都属于iterable类型var a = ['A', 'B', 'C'];var s = new Set(['A', 'B', 'C']);var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);for (var x of a) { // 遍历Arrayconsole.log(x);}for (var x of s) { // 遍历Setconsole.log(x);}for (var x of m) { // 遍历Mapconsole.log(x[0] + '=' + x[1]);}
2、for...in循环的是Array的属性var a = ['A', 'B', 'C'];a.name = 'Hello';for (var x in a) {console.log(x); // '0', '1', '2', 'name'}而for....of修复了这写bug,循环元素本身var a = ['A', 'B', 'C'];a.name = 'Hello';for (var x of a) {console.log(x); // 'A', 'B', 'C'}3、iterable内置的forEach函数  Array:var n=[1,2,3,4]n.forEach(function(element,index,array){// element: 指向当前元素的值// index: 指向当前索引// array: 指向Array对象本身console.log(element,'index=',index)})Set::Set与Array类似,但Set没有索引,因此回调函数的前两个参数都是元素本身var s = new Set(['A', 'B', 'C']);s.forEach(function (element, sameElement, set) {console.log(element);});Map:  Map的回调函数参数依次为value、key和map本身var c=new Map([['name','boady'],['age',12],['addr','深圳']])c.forEach(function(value,key,map){console.log(value,key)})如果不需要某些参数,可以省略掉var a = ['A', 'B', 'C'];a.forEach(function (element) {console.log(element);});

九、函数

[一、函数的定义和调用]1、定义函数的格式:function abs(x) {if (x >= 0) {return x;} else {return -x;}}解析:function指出这是一个函数定义;abs是函数的名称;(x)括号内列出函数的参数,多个参数以,分隔;{ ... }之间的代码是函数体,可以包含若干语句,甚至可以没有任何语句。函数遇到return返回,如果没有return也会返回只不过是undefined由于JavaScript的函数也是一个对象,上述定义的abs()函数实际上是一个函数对象,而函数名abs可以视为指向该函数的变量。因此还有一种方法:var abs =function(x){if (x >= 0) {return x;} else {return -x;}
}这种方式下的function(x){....}是个匿名函数,没有函数名,但是这个函数赋值给了abs,因此通过变量名abs就可以调用该函数,这种语法需要在函数体末尾加一个 ; 表示赋值语句结束。函数的调用:abs(10, 'blablabla'); // 返回10abs(-9, 20,'haha', 'hehe', null); // 返回9abs(); // 返回NaNabs( 'blablabla',10);//NaN2、arguments,只在函数内部起作用,指向调用者传入的所以参数function foo(x) {console.log('x = ' + x); // 获取传入的第一个元素10for (var i=0; i<arguments.length; i++) {    //对调用者传入的所有参数进行遍历  10, 20, 30console.log('arg ' + i + ' = ' + arguments[i]); }}foo(10, 20, 30);执行结果:x = 10arg 0 = 10arg 1 = 20arg 2 = 303、利用arguments,获得调用者传入的所有参数。也就是说,即使函数不定义任何参数,还是可以拿到参数的值:function abs() {if (arguments.length === 0) {return 0;}var x = arguments[0];return x >= 0 ? x : -x;}abs(); // 0abs(10); // 10abs(-9); // 94、rest参数由于JavaScript函数允许接收任意个参数,于是我们就不得不用arguments来获取所有参数function foo(a, b) {var i, rest = [];//i表示接收的2个参数ab,rest定义一个空列表用来接收多余的参数if (arguments.length > 2) {//判断如果传入参数的个数大于2个for (i = 2; i<arguments.length; i++) {rest.push(arguments[i]);//把传入多余的参数添加进入rest}}console.log('a = ' + a);console.log('b = ' + b);console.log(rest);
}标准写法:function foo(a, b, ...rest) {console.log('a = ' + a);console.log('b = ' + b);console.log(rest);}foo(1, 2, 3, 4, 5);// 结果:// a = 1// b = 2// Array [ 3, 4, 5 ]foo();// 结果:// a = undefined// b = undefined// Array []如果传入的参数连正常定义的参数都没填满,也不要紧,rest参数会接收一个空数组(注意不是undefined[二、变量作用域与解构赋值]1、如果一个变量实在函数内部定义的,他的作用域就在函数内部,外部不可以调用function foo() {var x = 1;x = x + 1;}x = x + 2; // ReferenceError! 无法在函数体外引用变量x如果两个不同的函数各自申明了同一个变量,那么该变量只在各自的函数体内起作用。换句话说,不同函数内部的同名变量互相独立,互不影响function foo() {var x = 1;x = x + 1;}function bar() {var x = 'A';x = x + 'B';}内部可以访问外部的变量,反之,则不可以function foo() {var x = 1;function bar() {var y = x + 1; // bar可以访问foo的变量x!}var z = y + 1; // ReferenceError! foo不可以访问bar的变量y!}2、变量提升JavaScript的函数定义有个特点,它会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部:function foo() {var x = 'Hello, ' + y;console.log(x);//Hello, undefinedvar y = 'Bob';}foo();解析:
虽然是strict模式,但语句var x = 'Hello, ' + y;并不报错,原因是变量y在稍后申明了。但是console.log显示Hello, undefined,说明变量y的值为undefined。这正是因为JavaScript引擎自动提升了变量y的声明,但不会提升变量y的赋值。javascripts看到的代码为:function foo() {var y; // 提升变量y的申明,此时y为undefinedvar x = 'Hello, ' + y;console.log(x);y = 'Bob';}为了避免此类问题,需要先在函数内部定义所有变量function foo() {varx = 1, // x初始化为1y = x + 1, // y初始化为2z, i; // z和i为undefined// 其他语句:for (i=0; i<100; i++) {...}}3、全局作用域
JavaScript默认有一个全局对象window,全局作用域的变量实际上被绑定到window的一个属性'use strict';var course = 'Learn JavaScript';
alert(course); // 'Learn JavaScript'
alert(window.course); // 'Learn JavaScript'以变量方式var foo = function () {}定义的函数实际上也是一个全局变量,因此,顶层函数的定义也被视为一个全局变量,并绑定到window对象:'use strict';function foo() {alert('foo');}foo(); // 直接调用foo()window.foo(); // 通过window.foo()调用4、名字空间
为了减少冲突把自己的所有变量和函数绑定到一个全局变量上面;// 唯一的全局变量MYAPP:var MYAPP = {};// 其他变量:MYAPP.name = 'myapp';MYAPP.version = 1.0;// 其他函数:MYAPP.foo = function () {return 'foo';};5、局部作用域
用let替代var可以申明一个块级作用域的变量:function foo() {var sum = 0;for (let i=0; i<100; i++) {sum += i;}// SyntaxError:i += 1;//只能在for循环内部访问,因为是块级作用域的变量}6、常量  const const PI = 3.14;PI = 3; // 某些浏览器不报错,但是无效果!PI; // 3.147、解构赋值// 如果浏览器支持解构赋值就不会报错:var [x, y, z] = ['hello', 'JavaScript', 'ES6'];// x, y, z分别被赋值为数组对应元素:console.log('x = ' + x + ', y = ' + y + ', z = ' + z);存在嵌套的赋值:let [x, [y, z]] = ['hello', ['JavaScript', 'ES6']];x; // 'hello'y; // 'JavaScript'z; // 'ES6'忽略某些元素的赋值:let [, , z] = ['hello', 'JavaScript', 'ES6']; // 忽略前两个元素,只对z赋值第三个元素z; // 'ES6'对嵌套对象进行赋值:var person = {name: '小明',age: 20,gender: 'male',passport: 'G-12345678',school: 'No.4 middle school',address: {city: 'Beijing',street: 'No.1 Road',zipcode: '100001'}};var {name, address: {city, zip}} = person;name; // '小明'city; // 'Beijing'zip; // undefined, 因为属性名是zipcode而不是zip// 注意: address不是变量,而是为了让city和zip获得嵌套的address对象的属性:address; // Uncaught ReferenceError: address is not defined变量名和属性名不一致的赋值:var person = {name: '小明',age: 20,gender: 'male',passport: 'G-12345678',school: 'No.4 middle school'};// 把passport属性赋值给变量id:let {name, passport:id} = person;name; // '小明'id; // 'G-12345678'// 注意: passport不是变量,而是为了让变量id获得passport属性:passport; // Uncaught ReferenceError: passport is not defined设置默认值:var person = {name: '小明',age: 20,gender: 'male',passport: 'G-12345678'};// 如果person对象没有single属性,默认赋值为true:var {name, single=true} = person;name; // '小明'single; // true声明过的再次赋值报错:// 声明变量:var x, y;// 解构赋值:{x, y} = { name: '小明', x: 100, y: 200};// 语法错误: Uncaught SyntaxError: Unexpected token =原因:这是因为JavaScript引擎把{开头的语句当作了块处理,于是=不再合法。解决方法是用小括号括起来:({x, y} = { name: '小明', x: 100, y: 200});8、使用场景:
获取当前页面地址和域名:
var {hostname:domain, pathname:path} = location;[三、方法]1、对象绑定方法:var xiaoming = {name: '小明',birth: 1990,age: function () {var y = new Date().getFullYear();return y - this.birth;}};xiaoming.age; // function xiaoming.age()xiaoming.age(); // 今年调用是29,明年调用就变成30了在一个方法内部,this是一个特殊变量,它始终指向当前对象,也就是xiaoming这个变量。所以,this.birth可以拿到xiaoming的birth属性。以对象的方式调用比如:xiaoming.age()        this指向对象xiaoming如果单独调用函数,比如getAge(),此时,该函数的this指向全局对象,也就是windowthis只在age方法function 的函数有用,在内部定义的函数this又指向undefined'use strict';var xiaoming = {name: '小明',birth: 1990,age: function () {function getAgeFromBirth() {var y = new Date().getFullYear();return y - this.birth;}return getAgeFromBirth();}
};
xiaoming.age(); // Uncaught TypeError: Cannot read property 'birth' of undefined解决方法:
var xiaoming = {name: '小明',birth: 1990,age: function(){var that=this;//先拿到this赋值给thatfunction function1(){var y = new Date().getFullYear();return y - that.birth;}      return function1();}
};
xiaoming.age();//292、绑定this指定对象  apply()    call()apply()把参数打包成Array再传入;call()把参数按顺序传入。Math.max.apply(null, [3, 5, 4]); // 5Math.max.call(null, 3, 5, 4); // 5
对普通函数调用,我们通常把this绑定为null。function getAge() {var y = new Date().getFullYear();return y - this.birth;}var xiaoming = {name: '小明',birth: 1990,age: getAge};xiaoming.age(); // 25getAge.apply(xiaoming, []); // 25, this指向xiaoming, 参数为空3、装饰器'use strict';	var count = 0;var oldParseInt = parseInt; // 保存原函数	window.parseInt = function () {count += 1;return oldParseInt.apply(null, arguments); // 调用原函数};// 测试:parseInt('10');parseInt('20');parseInt('30');console.log('count = ' + count); // 3四、高阶函数之map  reduce
传入函数f作为参数
function add(x, y, f) {return f(x) + f(y);
}
add(2,5,Math.abs)//x=2,y=5,Math.abs=f1、map  function pow(x) {return x **3;};var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];var results = arr.map(pow); // [1, 4, 9, 16, 25, 36, 49, 64, 81],把函数pow作用于arr的每个元素并返回一个新的Arrayconsole.log(results);使用for循环处理上面的问题:var f = function (x) {return x * x;};var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];var result = [];for (var i=0; i<arr.length; i++) {result.push(f(arr[i]));}2、reduce练习:利用reduce()求积:'use strict';
function product(arr) {return arr.reduce(function(x,y) { return x*y;}
);
}数字转换成字符串
var arr=[1,5,9]
function prd(arr){return arr.reduce(function(c,v){return c*10+v;}
)
};
prd(arr)//159五、高阶函数之fiter1、filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。var arr = [1, 2, 4, 5, 6, 9, 10, 15];var r = arr.filter(function (x) {return x % 2 !== 0;//返回奇数});r; // [1, 5, 9, 15]把一个Array中的空字符串删掉,可以这么写:var arr = ['A', '', 'B', null, undefined, 'C', '  '];var r = arr.filter(function (s) {return s && s.trim(); // 注意:IE9以下的版本没有trim()方法});r; // ['A', 'B', 'C']去除重复元素'use strict';varr,arr = ['apple', 'strawberry', 'banana', 'pear', 'apple', 'orange', 'orange', 'strawberry'];r = arr.filter(function (element, index, self) {return self.indexOf(element) === index;});console.log(r.toString());去除重复元素依靠的是indexOf总是返回第一个元素的位置,后续的重复元素位置与indexOf返回的位置不相等,因此被filter滤掉了2、回调函数var arr = ['A', 'B', 'C'];var r = arr.filter(function (element, index, self) {console.log(element); // 依次打印'A', 'B', 'C'console.log(index); // 依次打印0, 1, 2console.log(self); // self就是变量arrreturn true;});筛选素数:function get_primes(arr) {var r=arr.filter(function(element, index, self) {if (element <= 3) return element > 1;for (let i = 2; i < element; i++) {if (element % i == 0) return false;}return true;});return r;六、高阶函数之sortvar arr = [10, 20, 1, 2];
arr.sort(function (x, y) {if (x < y) {return 1;}if (x > y) {return -1;}return 0;
}); // [20, 10, 2, 1]
如果x<y  返回-1,x>y 返回1  升序排列
如果x<y  返回1,x>y 返回-1  降序排列---此处不是很理解---七、高阶函数之Array1、everyvar arr=['apple','banana','orange']console.log(arr.every(function(s){return s.length>0;
}));//因为所有元素都满足s.length>0
console.log(arr.every(function(s){return `s.toUpperCase()===s;
}))2、find 查找满足条件的第一个元素var arr=['apple','Als','Orange']
console.log(arr.find(function(s){return `s.toLowerCase()===s;//全部小写的元素
}));
console.log(arr.find(function(s){return `s.toUpperCase()===`s;//全部大写的元素
}))3、findindex 找到了返回满足条件的第一个元素的索引,没有找到返回-1
var arr = ['Apple', 'pear', 'orange'];
console.log(arr.findIndex(function (s) {return `s.toLowerCase() === s;
})); // 1, 因为'pear'的索引是1console.log(arr.findIndex(function (s) {return `s.toUpperCase() === s;
})); // -14、forEach  把每个元素依次作用于传入的函数,但不会返回新的数组var arr = ['Apple', 'pear', 'orange'];arr.forEach(console.log); // 依次打印每个元素八、闭包   把函数作为结果值返回1、function lazy_sum(arr) {var sum = function () {return arr.reduce(function (x, y) {return x + y;});}return sum;
}当我们调用lazy_sum()时,返回的并不是求和结果,而是求和函数:
var f = lazy_sum([1, 2, 3, 4, 5]); // function sum()调用函数f时,才真正计算求和的结果:
f(); // 15闭包实现求次方function make_pow(n) {return function (x) {return Math.pow(x, n);}}九、箭头函数
1、格式:x => x * x上面的箭头函数相当于:function (x) {return x * x;}x => {if (x > 0) {return x * x;}else {return - x * x;}}多个参数:// 两个参数:(x, y) => x * x + y * y// 无参数:() => 3.14// 可变参数:(x, y, ...rest) => {var i, sum = x + y;for (i=0; i<rest.length; i++) {sum += rest[i];}return sum;}如果要返回一个对象,就要注意,如果是单表达式,这么写的话会报错:// SyntaxError:
x => { foo: x }因为和函数体的{ ... }有语法冲突,所以要改为:// ok:
x => ({ foo: x })2、thisvar obj = {birth: 1990,getAge: function () {var b = this.birth; // 1990var fn = function () {return new Date().getFullYear() - this.birth; // this指向window或undefined};return fn();}};箭头函数修复了这个问题:var obj = {birth: 1990,getAge: function () {var b = this.birth; // 1990var fn = () => new Date().getFullYear() - this.birth; // this指向obj对象return fn();}};obj.getAge(); // 25箭头函数排序arr.sort((x, y) => {return x-y;负数调换位置});console.log(arr); // [1, 2, 10, 20]十、generator
1、格式:function* fib(max) {vart,a = 0,b = 1,n = 0;while (n < max) {yield a;[a, b] = [b, a + b];n ++;}return;}
执行:var f = fib(5);f.next(); // {value: 0, done: false}f.next(); // {value: 1, done: false}f.next(); // {value: 1, done: false}f.next(); // {value: 2, done: false}f.next(); // {value: 3, done: false}f.next(); // {value: undefined, done: true}用for...of迭代:for (var x of fib(10)) {console.log(x); // 依次输出0, 1, 1, 2, 3, ...
}自增id实例:function* next_id(id){var id = 0;while(1){yield ++id;}
}

十、标准对象

1、typeof获取对象的类型typeof 123; // 'number'typeof NaN; // 'number'typeof 'str'; // 'string'typeof true; // 'boolean'typeof undefined; // 'undefined'typeof Math.abs; // 'function'typeof null; // 'object'typeof []; // 'object'typeof {}; // 'object'
2、包装对象var n = new Number(123); // 123,生成了新的包装类型objectvar b = new Boolean(true); // true,生成了新的包装类型objectvar s = new String('str'); // 'str',生成了新的包装类型object
因为类型变了。所以:typeof new Number(123); // 'object'new Number(123) === 123; // falsetypeof new Boolean(true); // 'object'new Boolean(true) === true; // falsetypeof new String('str'); // 'object'new String('str') === 'str'; // false包装对象时缺少关键字new,会按照普通函数处理var n = Number('123'); // 123,相当于parseInt()或parseFloat()typeof n; // 'number'var b = Boolean('true'); // truetypeof b; // 'boolean'var b2 = Boolean('false'); // true! 'false'字符串转换结果为true!因为它是非空字符串!var b3 = Boolean(''); // falsevar s = String(123.45); // '123.45'typeof s; // 'string'总结规则:不要使用new Number()、new Boolean()、new String()创建包装对象;用parseInt()或parseFloat()来转换任意类型到number;用String()来转换任意类型到string,或者直接调用某个对象的toString()方法;通常不必把任意类型转换为boolean再判断,因为可以直接写if (myVar) {...};typeof操作符可以判断出number、boolean、string、function和undefined;判断Array要使用Array.isArray(arr);判断null请使用myVar === null;判断某个全局变量是否存在用typeof window.myVar === 'undefined';函数内部判断某个变量是否存在用typeof myVar === 'undefined'。一、date
1、获取系统当前时间var now = new Date();now; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)now.getFullYear(); // 2015, 年份now.getMonth(); // 5, 月份,注意月份范围是0~11,5表示六月now.getDate(); // 24, 表示24号now.getDay(); // 3, 表示星期三now.getHours(); // 19, 24小时制now.getMinutes(); // 49, 分钟now.getSeconds(); // 22, 秒now.getMilliseconds(); // 875, 毫秒数now.getTime(); // 1435146562875, 以number形式表示的时间戳
2、创建指定日期var d = new Date(2015, 5, 19, 20, 15, 30, 123);d; // Fri Jun 19 2015 20:15:30 GMT+0800 (CST)第二种创建方式:var d = Date.parse('2015-06-24T19:49:22.875+08:00');d; // 1435146562875d.getMonth(); // 5二、RegExp ---正则匹配---1、格式:第一种方式是直接通过    /正则表达式/      写出来,第二种方式是通过new RegExp('正则表达式')创建一个RegExp对象。两种写法是一样的:
var re1 = /ABC\-001/;
var re2 = new RegExp('ABC\\-001');//需要处理字符串转义问题
re1; // /ABC\-001/
re2; // /ABC\-001/var re = /^\d{3}\-\d{3,8}$/;
re.test('010-12345'); // true
re.test('010-1234x'); // false
re.test('010 12345'); // falseRegExp对象的test()方法用于测试给定的字符串是否符合条件。2、切分字符串'a b   c'.split(' '); // ['a', 'b', '', '', 'c']正常切分无法识别连续空格
'a b   c'.split(/\s+/); // ['a', 'b', 'c']  正则表达式切分'a,b, c  d'.split(/[\s\,]+/); // ['a', 'b', 'c', 'd']
'a,b;; c  d'.split(/[\s\,\;]+/); // ['a', 'b', 'c', 'd']3、分组var re = /^(\d{3})-(\d{3,8})$/;
re.exec('010-12345'); // ['010-12345', '010', '12345']
re.exec('010 12345'); // null 匹配失败var re = /^(\d+?)(1*)$/;去除贪婪匹配
re.exec('102311'); // ['102311', '1023', '11']4、全局搜索 g
var s = 'JavaScript, VBScript, JScript and ECMAScript';
var re=/[a-zA-Z]+Script/g;  //后面的g表示去全局匹配// 使用全局匹配:
re.exec(s); // ['JavaScript']
re.lastIndex; // 10re.exec(s); // ['VBScript']
re.lastIndex; // 20re.exec(s); // ['JScript']
re.lastIndex; // 29re.exec(s); // ['ECMAScript']
re.lastIndex; // 44re.exec(s); // null,直到结束仍没有匹配到三、Jsonnumber:和JavaScript的number完全一致;boolean:就是JavaScript的true或false;string:就是JavaScript的string;null:就是JavaScript的null;array:就是JavaScript的Array表示方式——[];object:就是JavaScript的{ ... }表示方式。1、序列化'use strict';var xiaoming = {name: '小明',age: 14,gender: true,height: 1.65,grade: null,'middle-school': '\"W3C\" Middle School',skills: ['JavaScript', 'Java', 'Python', 'Lisp']};var s = JSON.stringify(xiaoming);
console.log(s);JSON.stringify(xiaoming, null, '  ');//可以展示好看一点并进行缩进运行结果:
{"name": "小明","age": 14,"gender": true,"height": 1.65,"grade": null,"middle-school": "\"W3C\" Middle School","skills": ["JavaScript","Java","Python","Lisp"]
}还可以筛选指定属性:
JSON.stringify(xiaoming, ['name', 'skills'], '  ');
结果:
"{"name": "小明","skills": ["JavaScript","Java","Python","Lisp"]
}"传入函数进行处理对象的键值:function convert(key, value) {if (typeof value === 'string') {return value.toUpperCase();}return value;}JSON.stringify(xiaoming, convert, '  ');定义方法toJSON指定序列化的数据var xiaoming = {name: '小明',age: 14,gender: true,height: 1.65,grade: null,'middle-school': '\"W3C\" Middle School',skills: ['JavaScript', 'Java', 'Python', 'Lisp'],toJSON: function () {return { // 只输出name和age,并且改变了key:'Name': this.name,'Age': this.age};}
};JSON.stringify(xiaoming); // '{"Name":"小明","Age":14}'2、反序列化 JSON.parse()JSON.parse('[1,2,3,true]'); // [1, 2, 3, true]JSON.parse('{"name":"小明","age":14}'); // Object {name: '小明', age: 14}JSON.parse('true'); // trueJSON.parse('123.45'); // 123.45接收一个函数:var obj = JSON.parse('{"name":"小明","age":14}', function (key, value) {if (key === 'name') {return value + '同学';}elsereturn value;});console.log(JSON.stringify(obj)); // {name: '小明同学', age: 14}

十一、面向对象编程