本博客的js只讨论浏览器上的,可以开发网页的js,不考虑node.js
主要分为三个部分:
ECMAScript 也就是JavaScript语法
DOM 页面文档对象模型 对页面中的元素进行操作
BOM 浏览器对象模型 对浏览器窗口进行操作
后两者都是浏览器给js提供的api
js的hello world程序
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>js</title>
</head>
<body><script>alert('hello world')//这里可以用单引号 也可以用双引号表示</script>
</body>
</html>
但是弹框是在真实项目中不会建议使用的,因为比较影响用户体验
js也有多种方式来和html来进行结合
内嵌式:吧js代码写到script标签中
内联式:把js代码放到标签的特殊属性中
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>js</title>
</head>
<body><button onclick="alert('hello world')">这是个按钮</button><script></script>
</body>
</html>
外部式:把js代码写到单独的.js文件中,在html中引入这个js文件,使用script标签引入
这样可以把公共的js代码提取出来,方便多个页面来进行重复使用
但是当前学习还是以内嵌式为主,因为更为方便理解
注意:js里的注释支持使用 // 和 /* */
html注释:<!-- -->
CSS注释: /* */
js注释: // /* */
输出操作
console.log
类似于java的sout 使用的时候只需使用log就可以打出上述代码
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>js</title>
</head>
<body><script>console.log(hello);</script>
</body>
</html>
这个hello在页面看不见 但是在控制台可以找到,因为这里的内容不是给普通用户看的,而是给程序员调试用的。
定义变量
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>js</title>
</head>
<body><script>var name = '张三';let age = '19';//这里的var let 都是关键字 表示后面的名字是一个变量 不表示一个类型//只是var是老式写法 let是新式写法 使用后者let变量的各种特性就和java/c中的特性基本一致//具体的类型是根据后面=的值的类型来区分的//例如name就是string类型 age就是number类型console.log(name);console.log(age);</script>
</body>
</html>
注意:js里面不区分整数和浮点数,统一都是number类型
而且js中的变量类型是动态的(动态是运行时 静态是编译期)也就是说运行过程中变量类型 可以发生改变
int num = 10;
num = "hello";
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>js</title>
</head>
<body><script>let a = 19;console.log(typeof(a));a = "hello";console.log(typeof(a));</script>
</body>
</html>
注意:类型能不能改 和是否使用类型自动推导语法无关,例如Java和C++都可以使用自动类型推导,但是仍然是“静态类型”
动态类型提供了更灵活的编程方式,写一段代码就可以同时支持多种类型的数据,相当于自带泛型,但是类型过于灵活,如果是大项目就显得不太合适
基本数据类型
js中的数字不区分整数还是浮点数,统一都是number
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>js</title>
</head>
<body><script>let a = 1;console.log(a/2);console.log(typeof(a/2));</script>
</body>
</html>
特殊的数字值:
infinity 无穷大 大于任何数字 表示数字已经超过js表示的范围
-infinty 负无穷大 小于任何数字 表示数字已经超过js表示的范围
NaN 表示当前结果不是一个合法的数字
无穷大一般是浮点数除以零算出来的结果
字符串
js中字符串可以用单引号也可以用双引号
如果要输出有双引号或者单引号的字符串可以使用转义字符
或者在最外围使用单引号,在里面对引用的内容使用双引号
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>js</title>
</head>
<body><script>let name1 = "My name is \"LI\"";let name2 = 'My name is "LI"';console.log(name1);console.log(name2);</script>
</body>
</html>
字符串的长度
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>js</title>
</head>
<body><script>let name1 = "张三";console.log(name.length);</script>
</body>
</html>
字符串的长度意思是里面有几个字符,而不是几个字节,一个字符里面可以包含多个字节
字符串拼接
使用+来进行拼接
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>js</title>
</head>
<body><script>let a = "hello";let b = "world";console.log(a+b);</script>
</body>
</html>
也可以数字和字符串混着相加,会把数字隐式转换成字符串
字符串比较
直接使用 == 来进行比较
布尔类型
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>js</title>
</head>
<body><script>let a = true;console.log(typeof(a));console.log(a+10);</script>
</body>
</html>
但是java中进行boolean和整数类型混合运算就无法编译,我们称其为强类型语言(有部分支持但不是全部)
向js这种比较支持隐式类型转换的语言我们就叫弱类型语言
类型强就是不同的数据区分度更高界限更明确,类型弱就是不同的数据区分度低,界限更模糊
undefined和null(特殊类型)
undefined只有一个值就是undefined null只有一个值就是null
前者表示你这个类型没有被定义,此时就是undefined(例如敲错了length这个单词)
后者表示访问的变量是存在的,但是这个值是空的
三等号
== 适用于隐式类现转换
===不会进行隐式类型转换
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>test</title>
</head>
<body><script>let a = 10;let b = '10';console.log(a == b);console.log(a === b);</script>
</body>
</html>
&&和||
let a =10;b = a || 0;
b = a && 0;
//第一行为左侧表达式为真(或者隐式转换为true)此时就把a值赋给b 反之赋值给b
//第二行为左侧表达式为假(或者隐式转换为faluse)此时就把a的值赋值给b 反之赋值给a
创建数组
<script>let arr = new Array();let arr2 = [];</script>
两种方式都可以,创建的时候不需要声明长度因为js的数组长度是可以动态变化的,js的数组更接近于java的arraylist
创建数组的时候,可以同时指定初始值
let arr2 =[1,2,3,4];
js的数组允许里面存在不同类型的元素,而java则要求务必是相同类型
let arr3 = [1,'hello',true,[]];
<script> let arr = ['老王','老李','老张'];console.log(arr[1]);console.log(arr.length);console.log(arr);</script>
在java中下标越界访问的时候,会抛出异常,但是在js中会获取一个undefined的结果,
<script> let arr = ['老王','老李','老张'];console.log(arr[4]);</script>
<script> let arr = ['老王','老李','老张'];arr[4] = '老表';console.log(arr[4]);</script>
但是我们可以直接通过越界来赋值的方式去增添我们需要的元素,并且可以直接打印出来
<script> let arr = ['老王','老李','老张'];arr[6] = '老表';console.log(arr);</script>
当我们越过几个数组位置去赋值的时候,中间未被赋值的元素会变成empty
<script> let arr = ['老王','老李','老张'];arr['hello'] = '老师';console.log(arr['hello']);console.log(arr.hello);</script>
js的数组不仅仅式数组,还有map这样的效果,上述的arr.hello就是把这个数组当成了一个对象,其中的hello就是键值对,js的对象是可以值运行的时候随意新增属性的。js中要访问成员,既可以使用.也可以使用[](arr.hello = arr['hello'])
对于js数组来说,只有[]中为非负整数的时候,才会把操作看成操作下标,如果式其他类型的值,都会认为式数组的自定义属性。
数组新增和删除元素
可以使用push方法进行尾插(类似于arraylist的add方法)
使用pop来删除末尾的元素
<script> let arr = [];for (let i =0;i<10;i++){arr.push(i);}console.log(arr);let ret = arr.pop();console.log(ret);let ret1 = arr.pop();console.log(ret1);console.log(arr);</script>
数组中间位置的插入和删除
splice 既可以中间位置插入和删除,还可以进行元素的替换
<script> let arr =[1,2,3,4,5];//要在2和3之间插入一个元素‘hello’arr.splice(2,0,'hello')//第一个2为起始下标 第二个0为要取数组的长度 0就是不对数组原来的内容进行调整,也就是不删除 任何元素//如果第二个数字 0 为 1 的话就是把3替换成hello,为2就是把3和4替换成hello//第三个参数为要替换到数组指定范围的新的值console.log(arr);</script>
<script> let arr =[1,2,3,4,5];arr.splice(2,1,'hello','world')console.log(arr);</script>
<script> let arr =[1,2,3,4,5];arr.splice(2,1)console.log(arr);</script>
因为后面没有指定新的元素,这样就是值下标为2的开始处删除长度为1的元素,也就是删除3这个元素
函数
<script>function add(x,y){return x+y;}console.log(add('hello','world'));console.log(add(10,20));console.log(add(true,false));</script>
js这样的动态类型的语言自带了泛型机制,也不需要函数重载这样的语法(js的一个函数就能支持不同个数的参数,不要求形参和实参个数匹配)
当实参比形参多的时候,多出来的实参就不能通过形参获取到了
当实参比形参少的时候,多出来的形参就是undefined了
<script>function add(a,b,c,d,e,f,g){return a+b+c+d+e+f+g;}let ret = 0;ret = add(10,20);console.log(ret);ret = add(10,20,30);console.log(ret);ret = add(10,20,30,40);console.log(ret);ret = add(10,20,30,40,50,60,70,80);console.log(ret);</script>
解决方案:
<script>function add(a,b,c,d,e,f,g){if (a == undefined){a = 0;}if (b == undefined){b = 0;}if (c == undefined){c = 0;}if (d == undefined){d = 0;}if (e == undefined){e = 0;}if (f == undefined){f = 0;}if (g == undefined){g = 0;}return a+b+c+d+e+f+g;}</script>//或者<script>function add(a,b,c,d,e,f,g){a = a || 0;b = b || 0;c = c || 0;d = d || 0;e = e || 0;f = f || 0;g = g || 0;return a+b+c+d+e+f+g;}</script>//或者<script>function add(){let ret = 0 ;//arguments这个数组就包含了调用add方法的所有实参的值for(let i = 0; i <arguments.length; i++){ret+=arguments}return ret;}</script>
js中,函数是可以像普通变量一样进行赋值的,还可以作为另外一个函数的参数家或者是另外一个函数的返回值
<script>//先定义来一个变量,给变量进行赋值,赋的值式一个function,add的类型就是函数//同时也就相当于定义来一个匿名函数(也就是lambda表达式)let add = function(){let ret = 0;for(let i = 0;i<arguments.length;i++){ret += arguments[1];}return ret;}</script>
js值代码中尝试访问一个变量的时候,会先查找到当前代码块,如果当前代码块中没有,就会继续往上级代码块中查找,一直找到全局的作用域。
js把上述变量作用域查找规则称为 作用域链
<script>let num = 0;function test(){console.log(num);}test();</script>
对象
<script>let student = {name:'cxk',age: 20,gender: 'none',sing: function(){console.log("ji");},dance: function(){console.log("tsk");}};console.log(student.name);student.sing();student.dance();</script>
html中创建一个对象是不需要创建一个类的
构造函数
<script>function Student(name,age, gender){this.name = name;this.age = age;this.gender = gender;this.sing = function(singMsg){console.log(singMsg);};this.dance = function(){console.log(danceMsg);};}let student1 = new Student('cxk',20,'male','jntm','tsk');let student2 = new Student('cxkki',21,'female','jnbm','glgl');</script>
使用构造函数可以起到对象图纸的效果,想要什么对象就直接创建一个对象出来
js虽然有类的概念,但是不能提供封装和继承以及多态的思想,因为js并不是一个面向对象的编程语言