首先
先附上我看的这份教程吧!
其次其次,附上js几个常见的调试的代码
console.log(“console.log”);
console.info(“console.info”);
console.debug(“console.debug”);
console.warn(“console.warn”);
console.error(“console.error”);
最后-进入正题
基础知识
- Nunber:包含整数,浮点数,负数。其中 NaN表示不是一个数字, Infinity表示无限大,超出了js的计算范围;
- 字符串:可以使用单引号,也可以使用双引号引起来,没有字符,只有字符串;
- 布尔值true false
- 运算符:与或非 && || !
- 比较运算符 > < == === 其中 == 和 === 的区别是,==会自动转换数据类型, ===不会自动转换类型
- 特殊的情况:
- NaN === NaN;//false 而 isNaN(NaN);//true false==0;//true,false===0;//false
- 浮点数的比较不能直接比较,直接比较返回来的是false,要取他们之间的绝对值,小于某个阀值;
- null 和 undefine null表示为空,undefine表示未定义,类似于java的未初始化
- 数组,声明数组的两种方式 var arr=[23,56,48]; var arr = new array(1,63,45);
- 对象,对象是由一组键值对组成的无序的集合,类似于java的map集合。var person={ name:’zhangsan’,age:20}对象取值的时候以.的方式取值,例如 person.name
字符串常用的api
- 取某个字符 和数组一样,var s = “abc”; s[2] 的值是 c;
- 字符串一旦定义,是不可改变的,var str=”asdfg”;str[2]=”5”;alert(str); 最后弹出来的还是asdfg
- toUpperCase toLowerCase 将字符串转为大写(小写)
- indexOf 搜索指定字符串的位置。
- substring 截取字符串,传入1个参数时指从这里截取到结尾,两个参数表示从哪里到哪里。
数组常用的api
- 取值 arr[2] 取第三个值,如果长度为3,你下标写的是3,它不会报数组越界,而是返回给你一个undefine
- 赋值,和java一样,arr[2]=”dsa”;同样,赋值也不会报越界,如果超过了,会自动扩展,例如一个数组长度为3,那么arr[5]=”sad”; 那么执行完这句后,数组的长度会自动的扩展到6,而 arr[3] arr[4] 的值为undefine
- 取长度,直接使用数组的length属性就可以取到数组的长度。
- indexOf 取某个元素的索引,没有则返回-1;这个时候需要注意的是数据类型要一一对应,数组里面的是30,你indexOf(“30”); 返回来的是-1;
- slice()截取,和字符串的substring一样,当此函数不传任何参数的时候,将改数组复制一份。
- push 和 pop push表示向数组的末尾添加若干个元素,pop则表示从该数组的结尾删除一个元素。
- unshift 和 shift 和push,pop 一样。unshift表示往头部添加,shift表示从开头删除。
- sort() 排序,直接调用的话,按照自然排序。
- reverse() 反转
- splice 修改数组, arr.splice(2, 3, ‘Google’, ‘Facebook’);// 从索引2开始删除3个元素,然后再添加两个元素,arr.splice(2, 2); // 只删除,不添加,arr.splice(2, 0, ‘Google’, ‘Facebook’); // 只添加,不删除
- concat拼接数组,var arr = [‘A’, ‘B’, ‘C’];arr.concat(1, 2, [3, 4]); // [‘A’, ‘B’, ‘C’, 1, 2, 3, 4]
- join()var arr = [‘A’, ‘B’, ‘C’, 1, 2, 3];arr.join(“-“); // ‘A-B-C-1-2-3’; join里面不能不传。可以传”“
对象:
- 对象和java中的map集合类似,写法和C的结构体有点类似。
- 对象以键值对的形式出现,访问属性的时候用.来表示。属性名和属性值之间用分号来表示。
- 对象的属性名必须是一个有效的变量名,如果是一个包含有特殊符号的变量,必须用单引号引起来,否则这个属性无法使用。
- 获取属性的两种方式:entity.key entity[‘key’] 如果key里面有特殊的符号,必须使用第二种方式获取。
- in 判断某个属性是否存在,‘key’ in entity 判断entity中是否存在key属性。存在则true,不存在则false
- hasOwnProperty() 判断自身是否存在某个属性。entity.hasOwnProperty(‘key’); 和 in 不一样的是,in可以判断它父对象的属性,任何对象最终都继承自Object。
流程跳转
- if-else、和java没啥区别啊,支持嵌套,支持else if
- 循环
- for 和 java中的好像没啥区别啊。
for(var key in entity){
if(entity.hasOwnProperty('key')){
alert(entity.[key])
}
}
- for in 可以用来循环实体,用来把一个对象的所有属性都循环的取出来。
var a = ['A', 'B', 'C'];
for (var i in a) {
alert(i); // '0', '1', '2'
alert(a[i]);//'A','B','C'
}
- 循环还有while 和 do-while
Map
- Map和java一样,key不可以重复。
- Map的初始化:var map = new Map([[‘Michael’, 95], [‘Bob’, 75], [‘Tracy’, 85]]);
- map.get(‘key’);获取
- map.set(‘key’,value); 设置,如果这个键对应的值已存在,则覆盖。
- map.delete(‘key’); 删除
Set
- 和 java 中的set类似,里面的元素不能重复。
- set的初始化:var s2 = new Set([1, 2, 3]); // 含1, 2, 3
- set.add();添加 添加的时候可以重复添加,但不会有效果,也不会覆盖。
- set.delete();删除
Iterable
- 迭代器,可迭代的。array map set 都是属于iterable
- terable 可以用 for of 来循环遍历
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) { // 遍历Array
alert(x);
}
for (var x of s) { // 遍历Set
alert(x);
}
for (var x of m) { // 遍历Map
alert(x[0] + '=' + x[1]);
}
函数function
函数的定义
function abs(x){
if(x>0){
return x;
}else{
return -x;
}
}
function 函数的关键字,函数不需要指定返回值类型
abs 函数名
x 参数,如果有多个参数则要用逗号分开,参数不用指定类型
大括号之间的是函数体
函数执行到return则返回,不再执行下去。
- 函数的第二种定义的方式,将一个匿名的函数赋值给一个变量
var abs =function(x){
if(x>0){
return x;
}else{
return -x;
}
};
- 两种定义的方式实际上是一致的,不同的是,第二种需要在最后的大括号后面跟上一个分号,表示结束了。
- 函数的调用,调用函数和java差不多,函数名,然后小括号里面跟上参数。
当参数个数大于函数接受的参数个数的时候,后面的会直接忽略掉,当传入的参数个数小于函数可接受的参数个数的时候,会自动undefine补齐。 - rest 可变参数,函数可以接受一个个数可变的参数,其实就是一个数组,function abc(x,y,…rest)这个函数除了接受x和y两个参数外,还接收一个rest参数,函数调用的时候和其他一样。当调用的时候只传递两个参数的时候,rest为一个空数组,当调用的时候传递3个参数的时候,那就是长度为1的数组。rest必须是函数中最后一个参数,且必须前面有.
- argument 参数,它是所传进去函数的参数集。它只在函数中使用,使用起来和数组差不多,但不是一个数组。函数接受的参数个数为3个,但调用的时候传进去2个,那么argument里面就有2个,而不是3个。所以。argument实际上是参数的副本。是实际传递进去的。因为js是不限制参数的传递的个数的,所以argument经常用来判断传进去的参数的个数,来做进一步的。
- 函数的作用域:js中,函数支持嵌套。也就是函数里面可以有函数。里面函数可以访问外面函数的变量,外面函数就不能访问里面函数的变量。如果函数的名字重复,则使用本函数里面的。
- 全局作用域:当一个变量不是定义在function里面的时候,那么它就是一个全局的变量,作用域就是全局。可以使用windows来调用。
- 需要注意的是,函数里面的变量一定要 var 声明,不然就会变成一个全局变量。
方法
在一个对象中绑定函数,称之为这个对象的方法。例如:
var xiaoming={
name:'xiaoming',
birth:1990,
age:function(){
var y = new Date().getFullYear();
return y-this.birth;
}
};
- 上面的例子,age是匿名function计算出来的,这有别于其他,这样我们就可以做更多的事情了
- 其中例子中有一个关键字 this this到底是啥?this指向的是调用函数的对象。
高阶函数
函数接收变量,变量可以指向函数,那么一个可以接收函数作为变量的函数就是高阶函数。
function add(x,y,f){
return f(x)+f(y);
}
- 这就是一个高阶函数,函数中的第三个参数就是一个函数。例如,add(-5,6,abs),运行的结果是11
- map也是一个高阶函数,它对数组array起作用,可以对array里面的每一个元素做相应的动作。
- array=[1,2,3]; fun = function(x){return x*x} 那么生成的新的数组那就是[1,4,9],对原数组中的每一个元素做平方的操作。
- array.map(fun);这里是指,对数组array里面的每个元素都调用一下fun函数,生成一个新的数组,
- reduce 也是一个高阶函数,也对array起作用,指对array里面的元素做一些动作,使之最后得到一个结果,例如我要对数组[1,2,3] 里面的每一个元素加起来,也就是累加。那么可以使用reduce。例如下面的例子,运行的结果是25.
var arr = [1, 3, 5, 7, 9];
arr.reduce(function (x, y) {
return x + y;// 25
}
);
- filter 同样是一个对array起作用的一个高阶函数,它可以过滤掉一些元素,保留一些元素形成一个新的数组。是否保留某个元素由传递进去的函数的返回的true或者false决定,那么,传递进去的函数的返回值就必须是一个boolean类型的返回值。例:var arr=[1,2,3,4]; arr.filter(function (x) { return x % 2 !== 0; }); 得到的新的数组为[1,3],例如下面的例子运行的结果是: [1, 2, 10, 20]。
var arr = [10, 20, 1, 2];
arr.sort(function (x, y) {
if (x < y) {
return -1;
}
if (x > y) {
return 1;
}
return 0;
});
//这样就可以实现数字的排序,相应的,如果是按照字母来排序的话,
//可以全部转化成大写或者小写来排序(转化成大写 toUpperCase(),)
- 高阶函数不仅可以将函数作为一个参数传递进去,还可以将一个函数作为返回值进行返回。
//高阶函数的闭包
function sun(arr){
//返回一个函数
return function(){
//这个返回的函数的返回值是对数组做reduce
return arr.reduce(function(x,y){
//reduce做的是对数组里面的元素进行累加
return x+y;
});
}
}
var syy=[1,2,3];//数组
var fun = sun(syy);//函数。得到的是一个函数,也就是说fun是一个函数
var ff = fun();//ff 是函数 fun 执行得到的结果。
alert(ff);
//这就是典型的将函数作为返回值的情况。
//就上面这个例子,如果再次调用一下 var fun1=sun(ssy);
//得到一个新的函数fun1 和fun 是两个不同的函数,
//当你对它们做 === 的操作的时候,返回来的是false,
//但对函数 fun fun1 的返回值做 === 的操作,返回的是 true
//fun() === fun1();//true
闭包
在js中,方法里面可以读取全局的变量,而在方法外面是不能访问方法里面定义的变量的,所以,要在外面访问方法里面的变量,这就是函数的闭包。
所以,闭包就是定义在一个函数里面的函数,本质上,闭包就是连接函数里面和外面的一个桥梁
箭头函数
- 箭头函数相当于匿名函数,只用一个箭头来表示
例如 function(x){return x*x;} 可以写成这样 x => x*x;
也就是说,1,省略了 function 的声明 2,参数也省略了用小括号包裹 3,函数体也省略了用大括号包裹 4,返回也省略了return 关键字。 - 不是所有的箭头函数都可以这么省略的,function是可以省略的,其他需要注意的是
- 函数体超过一行的时候就要用大括号括起来,并且return也不能省了;
- 参数是两个或者两个以上,也要用小括号括起来,没有参数也要用小括号;
- js函数的返回值是可以返回一个对象的,所以,当一个函数返回一个对象的时候。例如 function(x){return {name:x}} 这个函数,返回的是一个对象,这个对象中只有一个属性为name,那么使用箭头函数就不能这样写。x =>{name:x} 而是要把这个对象用小括号包起来,也就是这样 x => ({name:x})
- this,箭头函数中的this和普通函数的this是有却别的,普通函数里面的this是在运行的时候决定的,也就是谁调用,this指向的就是谁,而箭头函数是,谁绑定,this就指向谁。
Generator
- generator是一个新的数据类型,和方法差不多,不同的是,方法每次只能返回一个,而generator能够返回多次。如果我们要返回多个参数的话,那么就要用到数组,一次性的返回多个参数,而generator不用,可以一次一次的返回,这就是他们最大的区别
- 一次一次返回和一次返回全部也有千差万别的,一次一次的返回可以做到实时性,而一次返回多个,就要等到函数全部执行完毕才能接收到返回值
- generator的声明和函数差不多,只是多了个* 函数的声明是:function 而generator 的声明是function* 。
- generator也是遇到return的时候就结束函数,中间返回数据则使用yield,当执行到yield的时候,函数就暂停了,等到下一个返回的时候才继续执行。还有一点区别是,函数调用是这样的: fun(s) fun为函数名,s为参数。而generator调用是这样的 var f = fun(s); f.next();调用next的时候才是正式的调用,当执行到yield的时候就暂停了,等到下一次的调用,当函数已经执行完毕了,也就是执行到return的时候,就不要再继续调用next了,其实generator的返回的时候是这样的[value:0,done:false],其实返回的是一个对象,该对象里面有两个属性,一个是要返回的数据value,一个是返回是否已经全部完成done,当返回的done是true的时候,函数就执行完毕了。所以,执行generator的时候有一种类似于Java中for each 循环的方式:for…of… 来循环迭代对象,就变成了这样 for(var v of fun(3)){…函数体…},这样我们就可以在函数体里面对v做操作了。
Js标准对象
JavaScript中,标准的对象有,Number,String,Boolean,undefine,function,Object
alert(typeof 123);//Number
alert(typeof NaN);//Number
alert(typeof "Nam");//String
alert(typeof true);//booleam
alert(typeof undefine);//undefine
alert(typeof Math.abs);//function
alert(typeof null);//Object
alert(typeof []);//Object
alert(typeof {name:"xiaoming"});//Object
- number,string,boolean,undefine,function是可以用typeof 来判断的。 object就不行了,因为数组和null都是Object,如果要判断数组可以使用Array.isArray(arr) 来判断,如果判断null可以使用 ===
对象的包装
Number,String,Boolean都有其对应的类,类似于java的装箱拆箱。但装箱后,那么数据类型就不再是基本的标准类型了,而是Object了。所以,装箱后,再去判断是否相等,都是false。123 === new Number(123); //false 因为前面的是数字类型,而后面的是Object类型。
- 不要使用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’。
任何对象都有toString的方法,但null和undefine是没有的。number调用toString是会报SyntaxError,需要如下处理:
- 123.toString(); // SyntaxError
- 123..toString(); // ‘123’, 注意是两个点!
- (123).toString(); // ‘123’
Date对象
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形式表示的时间戳
//new一个Date对象,还可以使用:
var d = new Date(2015, 5, 19, 20, 15, 30, 123);
var d = Date.parse('2015-06-24T19:49:22.875+08:00');
var d = new Date(1435146562875);
//第一种指明了年月日时分秒毫秒,
//第二种直接由字符串转换而来,
//第三种传入一个时间戳,也就是毫秒数。
//Date还有一个方法,转换成本地时间,toLocalString()
//可以转换成当前时区的时间,还可以转换成UTC时间,toUTCString()
//获取当前的时间戳,Date.now() 老版本的ie需要用new Date().getTime();
正则表达式
创建一个RegExp对象的两种方式
- var re = /abc-101/;
- var re = new RegExp(“abc\-101”);
要匹配的时候直接调用test方法即可,re.test(“1244ds”);这个方法返回的是一个boolean
字符串的切割 split() 这个方法可以接收字符,字符串,也可以接受一个正则表达式,也就是说可以根据正则表达式来匹配,在进行分割。
JSON
- js中,支持Json的String字符串和对象直接互相转换.
- 字符串转换成js:JSON.parse(obj);,json对象转换成字符串:JSON.stringify(str);
- JSON.stringify(value,releace,space);完整的语法是这样的,后面两个为可选参数
- releace表示筛选,筛选可以传递一个数组,也可以传递一个方法进去,当传一个数组进去的时候,表示保留该数组里面的这几个key对应的key和value。当传递一个方法的时候,方法接收的是key和value,表示方法对其进行处理。
- space表示间隔,也就是每一个键值对之间用什么分开。
var xm = {name:"xiaoming",age:12};
//表示只保留age字段,然后用空格进行分隔。
var sxm = JSON.stringify(xm,['age'],' ');
alert(sxm);
//方法表示如果value是字符串,
//就将value全部转换成大写,不是就照原样返回。
var sxm1 = JSON.stringify(xm,function(key,value){
if(typeof value === 'string')
return value.toUpperCase();
return value;
});
alert(sxm1);
//将字符串转换成对象的时候处理该对象
var sxm2 = JSON.stringify(xm);
var xm2 = JSON.parse(sxm2,function(key,value){
if(key === 'age'){
return value*2;
}
return value;
});
alert(JSON.stringify(xm2));
面向对象
js和java,c#不同的是,它两都是利用类(class)来创建对象,js是利用原型来指向某个对象来创建。
var Student={
name:"xh",
birth:1990,
age:function(){
return new Date().getFullYear()-this.birth;
}
};
var stu = new Student("xiaoming");
创建对象的时候调用Object.create(objectName);来创建,里面只需要传入相应的对象名就可以了。
function Student(name){
this.name=name;
this.say=function(){
alert("hello:"+this.name);
}
};
function createStudent(names){
var stu = Object.create(Student);
stu.name = names;
return stu;
}
var st = createStudent("xiaoming");
alert(st.name);
继承,JS的对象也支持继承。
Student.call(this,name);这句表示继承自Student,调用Student的构造函数创建一个对象,并给构造函数传递的参数为name。this是一定要传的,其他可以不传,不传的话,Student里面的name有没有默认值,没有那就是undefine。
function Student(name){
this.name=name;
this.say=function(){
alert("hello:"+this.name);
}
};
function PrimaryStudent(names){
var pri = Student.call(this,names);
this.age = 12;
}
var pri = PrimartStudent("PRI");
alert(pri.name+"--"+pri.age);
js创建对象也可以使用构造函数来创建对象,如下:
class Student{
constructor(names){
this.name = names;
}
hello(){
alert(this.name+":hello!");
}
}
class PriStu extends Student{
constructor(names,grades){
super(names);
this.grade = grades;
}
say(){
alert(this.name + "-*-" + this.grade);
}
}
var stu = new Student("stu");
stu.hello();//stu:hello!
var pstu = new PriStu("pstu",99);
pstu.say();//pstu-*-99
浏览器对象
window 窗口
- window.inneeHeight 和 window.innerWidth 表示浏览器内部,网页的宽和高
- window.outerHeight 和 window.outerWidth 表示整个浏览器的宽和高
navigator导航
- navigator.appName 获取浏览器名称
- navigator.appVersion 获取浏览器的版本
- navigator.language 获取浏览器的语言
- navigator.platform 浏览器平台,也就是操作系统类型
- navigator.userAgent 为浏览器设置的 userAgent字符串
screen 屏幕
- screen.width 整个屏幕的宽
- screen.height 整个屏幕的高
- screen.colorDepth 屏幕的色彩的位数 8 16 24 等
location 对象
- location.href 表示获取当前页面的完整的url
- location.protocol
- location.host
- locaton.port
- location.pathname
- location.search
- location.hash
- locationg.assign() 加载一个页面
- location.reload() 重新加载页面
document 对象
- document.title 可以获取当前网页的标题
- document.cookie 可以获取浏览器的cookie
- document.getElementById 根据Id来获取元素
- document.getElementsByTagName 根据Tag 来获取页面上的元素
- document.getElementsByClassName 根据css的类名来获取页面上的元素
- document.history 表示获取该标签卡的历史记录
- document.forward() history.back() 表示前进和后退
Dom操作
更新节点的信息
document.getElementById('pId').innerHTML='asd';
表示将id为pId的节点里面的文本内容更改为asd
dom节点的更新,不仅可以改变里面的内容,还可以改变该节点里面的结构,也就是插入html代码
插入
代码的作用是:当点击button按钮的时候,在id为pId的节点里面的最后追加一个a节点,a节点的超链接是#,内容为369,创建一个节点要使用document.create,而不是用上面的一种,上面的那种,会被认为是字符串,而不是节点。
追加还有一种操作是,在某个节点前面追加:
doc.insertBefore(odd,redoc);
这句的意思是:在doc节点里面的redoc节点之前插入odd节点
删除
删除节点直接使用removeChild方法即可
document.getElementById('ppId').parentElement.removeChild(document.getElementById('ppId'));
表单操作
表单的基本类型,
input 标签
- type = “text” 普通文本
- type = “password” 密码,口令
- type = “radio” 单选按钮 一组单选按钮的name要相同才能正常实现单选
- type = “checkbox” 多选按钮
- type = “rest” 清空表单按钮
- type = “file” 文件
- type = “hidden” 隐藏
- type = “image” 图片形式的按钮
- type = “button” 普通按钮
- select标签 选择一项,也就是下拉菜单
- H5中的新控件中,type还有多种类型
- date 日期
- week 第几周
- time 时间
- month 月份
- color 颜色选取
获取元素
首先先获取到表单里面的对象
var val = document.getElementById(“id”).value;
设置元素里面的值
document.getElementById("id").value="123";