JS的编写位置
-
可以将js代码编到标签的onclick属性中,当我们点击按钮时,js代码才会执行
<button onclick="alert('讨厌,你点我干啥')">点我一下</button>
-
可以将js代码写在超链接的href属性中,这样当点击超链接时,会执行js代码
<a href="javaScript:alert('让你点你就点!!');">你也点我一下</a>
-
特殊情况:这种常用于控制超链接不跳转
<a href="javaScript:;">你也点我一下</a>
以上这些情况虽然都能实现想要的效果,但是对于JS来说,结构和行为耦合性太高,不利于后期维护;因此一般推荐以下几种方式:
- 写在script标签中
- 写在外部文件中,然后通过script标签引入(css文件是通过link标签引入)
<script type="text/javascript" src="js/script.js"></script>
推荐使用:写在外面可以在不同的页面中同时引入,也可以利用到浏览器的缓存机制。
注意:script标签一旦用于引入外部文件了,就不能在编写代码了,及时编写了浏览器也会忽略,以下代码中alert会被忽略。
<script type="text/javascript" src="js/script.js">alert(“我是script标签中的代码”)</script>
那么如果引入了以后,需要编写则可以在创建一个script标签用于编写内部的JS的代码
<script type="text/javascript" src="js/script.js">alert(“我是script标签中的代码”)</script>
<script type="text/javascript">alert(“我是script标签中的代码”)</script>
JS的基本语法
注释:
- /* …*/:单行注释
- //:多行注释
基本语法
- JS中严格区分大小写;
- JS中每一条语句以分号(;)结尾,如果不写分号,也能执行,但是浏览器会自动添加,就会消耗一些系统资源,而且有的时候,浏览器会加错分号,此时语义就会发生错误;
- JS中会自动忽略多个空格和换行,因此我们可以利用空格和换行对代码进行格式化
字面量和变量
字面量:都是一些不可改变的值,比如:1,2,true,null等;字面量都是可以直接使用的,但是一般都不会直接使用字面量;
变量:变量可以用来保存字面量,而且变量的值是可以任意改变的,开发中一般都是通过变量去保存一个字面量;
- 声明变量:ES6以前使用var关键字,ES6以后使用let关键字;var a ;
- 为变量赋值:a = 123;
- 声明赋值同时进行: var a = ‘hi’;这样初始化变量不会将它标识为字符串类型,只是一个简单的赋值。随后不仅可以改变保存的值,还可以改变值的类型
var和let的区别
- 如果在全局作用域中用var声明,此变量会默认成为window的一个属性,let声明的变量是不会添加到window对象中的;
- let声明的范围是块级作用域(用{}包含的区域),var声明的范围是函数作用域;
- var声明的变量有变量提升的特性,而let没有
- var可以允许重复声明相同变量,后者会覆盖前者,而let不能重复声明相同变量
标识符
标识符:在JS中所有可以自主命名的都可以称为标识符,比如变量名,函数名,属性名均属于标识符
命名规则:
- 标识符中可以含有字母、数字、下划线、美元符号
- 标识符不能以数字开头
- 标识符不能是JS中的关键字或保留字
- 标识符一般都采用驼峰命名法:首字母小写,每个单词开头字母大写,其余字母小写
注意:JS底层保存标识符时实际上采用的是Unicode编码,所以理论上来说utf-8中含有的内容都可作为标识符,比如说中文,但是虽然能用,但不合规范,最好不要用
数据类型
数据类型指的就是字面量的类型,在JS中一共有6种基本数据类型:String字符串,Number数值,Boolean布尔值,Null空值,Undefined未定义,Symbol符号;还有一种引用数据类型Object对象
字符串String
- 在JS中字符串需要使用引号引起来;
- 使用双引号,单引号均可,但是不要混着用
- 引号不能嵌套,双引号里不能放双引号,单引号中不能放单引号,但是双引号里可以嵌套单引号,单引号里可以嵌套双引号
str= "我说:'今天天气真不错!'"
- 如果非要使用相同的引号嵌套,那么需要使用\进行转义
str= "我说:\"今天天气真不错!\""
。其中\"
表示双引号,\'
表示单引号,\n'
表示换行,\t
表示制表符(tab键),\\
表示\
,所以打印斜杠时,需要写两个斜杠 alert("str")
输出字面量字符串str;alert(str)
输出变量str
Number数值
- 在JS中所有的数值都是Number类型,包括整数和浮点数(小数)
let a = 123
数字123;VALUE- 在JS中可以使用Number.MAX_VALUE表示数字的最大值 (1.7976931348623157e+308);如果使用Number表示的数字超过了最大值,则会返回一个Infinity表示正无穷,-Infinity表示负无穷;
console.log(Number.MAX_VALUE * Number.MAX_VALUE)
,输出Infinity; - 注意:Infinity是一个字面量,所以将Infinity赋值给a时,不用加双引号
a = Infinity
- 使用typeof检查Infinity时,会返回一个number类型
- NaN是一个特殊的数字,表示Not A Number(不是一个数字,非法数字),当字符串乘一个字符串就会返回NaN;使用typeof检查NaN时,会返回一个number类型
- 在JS中可以使用Number.MIN_VALUE表示数字的最小值 (5e - 324),这个最小值并不是负的Number.MAX_VALUE,从意义的上来看应该为大于0的最小值
- 在JS中整数的运算基本都能保持精确,但是如果使用JS进行浮点数运算,可能得到一个不精确的结果,eg :
var a = 0.1 + 0.3
,所以不要使用JS进行对精确度要求比较高的运算,尽量让服务器去进行运算。
Typeof
运算符typeof来检查一个变量的类型
语法:typeof 变量
返回值:检查字符串时,会返回string;检查数值时,会返回number
布尔值
布尔值只有两个:true(真)和false(假)
写法:var bool = true
使用typrof检查类型返回boolean
Null和Undefined
Null类型的值只有一个,就是null;null这个值专门表示一个为空的对象
注意:使用typeof检查null时,返回的是一个Object的对象
Undefined类型的值也只有一个,就是undefined;表示未定义
当声明一个变量,但是并不给变量赋值时(变量声明了但是未赋值),他的值就是undefined
使用typeof检查undefined时,返回的是undefined
强制类型转化
将其他数据类型转化为String
方法一:调用被转化数据类型的toString()方法
var a = 123;
var b = a.toString();
注意:
- 改方法不会影响到原变量,它会将转化的结果返回,也就是说他不会影响到a的值,a还是number123,b才是String123
- null和undefined这两个值没有toString方法
方法二:调用String函数,并将被转化的数据作为参数传递给函数
let a = 123;
let b = String(a);
使用String()函数做强制类型转化时,对于Number和Boolean实际上就是调用的toString()方法;但是对于null和undefined,就不会调用toString()方法,他会将null和undefined直接转化为“null”和“undefined”
将其他数据类型转化为Number
方法一:使用Number()函数
let a = 123;
let b = Number(a);
转化情况:
- 如果字符串转化为Number
- 如果是纯数字的字符串,则直接将其转换为数字
- 如果字符串中有非数字的内容,则转化为NaN
- 如果字符串是一个空串,或者是一个全是空格的字符串,则会转化为0
- 如果布尔值转为Number
- true转化为1
- false转化为0
- 如果Null转化为数字
- 结果为0
- 如果undefined转化为数字
- 结果为NaN
注意:Number有局限,一旦被转化的数值有一点非法的内容,就会转化为NaN;比如,使用css读取出来a=“123px”,此时需要加10px,如果使用Number直接转化a,得出来的结果为NaN。此时就需要方式二了。
方法二:使用函数parseInt()和parseFloat ()
这种方式专门用于字符串
- parseInt()把一个字符串中有效的整数内容取出来转化为一个整数,eg
"123a567px"转化为123,"b123a567px"转化为NaN,"123.567px"转化为123
- parseFloat ()把一个字符串中有效的小数内容取出来转化为一个浮点数
- 如果对非String类型的值使用parseInt()或parseFloat(),会将其先转为String,然后再操作
将其他数据类型转化为Boolean
方法一:使用Boolean()函数
- 数字转布尔:除了0和NaN,其余的都是true
- 字符串转布尔:除了空串其余的都是true
- null和undefined都会转化为false
- 对象也会转化为true
方法二:(隐式类型转化)
- 为任意的数据类型做两次非运算,即可将其转化为布尔值
其他进制的数字
- 在JS中,如果需要表示16进制的数字,则需要以0x开头
let a = 0x10;console.log(a)
;注意输出时还是会转化为十进制输出,因此a打印出来为16 - 如果需要表示8进制的数字,则需要以0开头
- 如果需要表示2进制的数字,则需要以0b开头,但是不是所有的浏览器都支持
- 像“070”这种字符串,有的浏览器会当做8进制解析,有的浏览器会当成10进制来解析,因此我们可以在parseInt()中传递一个第二个参数,来指定数字的进制
let a = "070"; a = parseInt(a,8)
运算符
运算符也叫操作符,通过运算符可以对一个或者多个值进行运算,并获取运算结果。比如:typeof就是运算符,可以来获得一个值的类型,会将该值的类型以字符串的形式返回
算数运算符
- 当对非Number类型的值进行运算时,会将这些值转化为Number然后再进行运算;其中true为1,false为0,null为0
- 任何值和NaN做运算都得NaN
+运算符:
- 可以对两个值进行加法运算,并将结果返回;
- 如果对两个字符串进行加法运算,则会做拼串,将两个字符串拼接为一个字符串,并返回
- 任何的值和字符串做加法运算,都会先转化为字符串,然后再和字符串做拼串的操作 ,所以可以后面加一个空串,将任意数据类型转化为字符串(隐式的类型转化,由浏览器自动完成,实际上也调用了String方法)
-,*,/运算符:
- 可以对两个值进行减法,乘法运算,除法运算并将结果返回;
- 任何值在做减法,乘法,除法运算时都会自动转化为Number
- 可以利用这一特点做隐式的类型转化,通过为一个值 -0,*1,/1来将其转化为Number
%运算符:取模
一元运算符
一元运算符:只需要一个操作数
正号+:不会对数字产生任何影响
负号-:负号可以对数字进行负号的取反
对于非Number的值会先转换为number值在进行运算
可以对一个其他的数据类型使用+,来将其转化为Number
自增
- 通过自增可以使变量在自身的基础上加1;
- 自增分为两种:后++(a++)和前++(++a),无论是a++还是++a,都会立即使原变量的值自增1,不同的是a++和++a的值不同,a++的值等于原变量的值(自增以前的值),++a的值等于自增后的值;
自减
- 通过自增可以使变量在自身的基础上加1;
- 自减分为两种:后–(a–)和前–(–a),无论是a–还是–a都会立即使原变量的值减1,不同的是a–和–a的值不同,a–的值等于原变量的值(自减以前的值),–a的值等于自减后的值;
逻辑运算符
- !非:对布尔值进行取反操作,如果对非布尔值进行运算,则会将其转化为布尔值,然后再取反。所以可以利用该特点将其他的数据类型转化为布尔值(可以为一个任意的书库类型取两次反,来将其转化为布尔值)
- &&与:可以对符号两侧的值进行与运算,只要有一个false就返回false,只有两个值均为true时,才会返回true
- ||或:可以对符号两侧的值进行或运算,只要有一个true就返回true,只有两个值均为false时,才会返回false
非布尔值的与或运算
会先将其转化为布尔值,然后在运算,并且返回原值,
- 与运算:如果第一个值为true,则必然返回第二个值;如果第一个值为false,则直接返回第一个值
- 或运算:如果第一个值为true,则直接返回第一个值;如果第一个值为false,则直接返回第二个值
赋值运算符
- a = a+5 等价于 a += 5;
- a = a-5 等价于 a -= 5;
- a = a*5 等价于 a *= 5;
- a = a/5 等价于 a /= 5;
- a = a%5 等价于 a %= 5;
关系运算符
大于号>,小于号<,大于等于>=,小于等于<=
- 对于非数字类型的会将其转化为数字在进行运算。
- 任何值和NaN做任何比较都是false
- 如果关系运算符的两遍都是字符串,那么不会将其转化为数字进行比较,而是会分别比较字符串中字符的Unicode编码,并且在比较字符编码时,是一位一位进行比较的,如果两位一样,则比较下一位,所以借用它来对英文进行排序
- 如果比较的两个字符串型的数字,可能得到结果不对,因此在比较两个字符串型的数字时,一定要转型
相等运算符(==)
- 相等返回true,否则返回false
- 当使用==来比较两个值时,如果值的类型不同,则会自动进行类型转换,将其转换为相同类型,然后在进行比较
- null和0不相等
- undefined衍自于null,所以这两个值做判断时,会返回true
- NaN不和任何值相等,包括它本身
console.log(NaN == NaN)
,输出false - 判断b的值是否是NaN,使用
let b = NaN; console.log(b == NaN);
输出肯定为false,无法判断,因此,可以通过isNaN()
函数来判断一个值是否为NaNconsole.log(isNaN(b))
,是NaN返回true,否则返回false
不相等运算符 (!=)
- 不相等用来判断两个值是否不相等,如果不相等返回true,否则返回false
- 不相等也会对变量进行自动的类型转换,如果转换后相等也会返回false;
console.log("1" != 1)
返回false;
全等运算符(===)
- 用来判断两个值是否全等,它和相等类似,不同的是不会做自动的类型转化
- null和undefined相等但不全等
不全等运算符(!==)
-用来判断两个值是否不全等,它和不相等类似,不同的是不会做自动的类型转化
条件运算符(也称三元运算符)
语法:条件表达式?语句1:语句2;
流程:条件运算符在执行时,首先对条件表达式进行求值,如果该值为true,则执行语句一,并返回执行结果;如果该值为false,则执行语句2并返回执行结果;
let a = 30; let b = 43; let c = 50;
let max = a > b ? a > c ? a : c : b > c ? b : c;
//等同于下面的写法:
let max = a > b ? (a > c ? a : c) : (b > c ? b : c)
运算符的优先级
在表中越靠上优先级越高,优先级越高越优先计算,如果优先级一样,则从左往右计算;如果想要改变优先级,使用括号改变即可
语句
语句是按照自上而下的顺序一条一条执行的,在JS中可以使用{}来为语句进行分组。而同一个{}中的语句我们称为是一组语句,他们要么都执行,要么都不执行。一个{}中的语句也称为一个代码块,在代码块的后边就不用写分号了。JS中的代码块,只具有分组的作用,没有其他用途。
条件判断语句
prompt函数:返回值是String类型,如果想要得到的是number类型,则var num1 = +prompt("请输入一个数:")
- if语句
- switch语句:如果被判断的变量都是同一个且都是判断是否全等,此时就可以用switch;switch…case…语句,在执行时会依次将case后的表达式的值和switch后的条件表达式的值进行全等比较,如果执行结果为true,则从当前case处开始执行且当前case后的所有代码都会执行,如果不想执行后面的,可以使用break来退出执行语句,break语句除了可以跳出switch语句,也可以跳出while语句;如果所有的结果都为false,则只执行default后的语句。
var num = 1;
switch(num){
case 1:
console.log("壹");
break;
case 2:
console.log("贰");
break;
case 3:
console.log("叁");
break;
default:
console.log("非法数字");
}
- while循环语句:反复执行一段代码多次。循环三要素:初始化一个变量,循环判断条件,循环体
var i = 1;
while(i < 10){
document.write(i++ +"<br />")
}
- do…while循环:先执行循环体,在判断循环条件
do{
document.write(i++ +"<br />")
}while(i < 10);
- for循环
var i = 0;
for(;i<10;){
alert(i++);
}
break和continue
- break关键字可以用来退出switch或者循环语句;
- 不能在if语句中使用break和continue;
- break关键字会立即终止离他最近的循环语句,下图就只会输出五次外层循环,不会输出内层循环;
for(var i=0;i<5;i++){
console.log("@外层循环"+i};
for(var j=0;j<5;j++){
break;
console.log("内层循环:"+j)
}
}
- 可以为循环语句创建一个label,来标识当前的循环,label:循环语句;使用break语句时,可以在break后跟着一个label,这样break将会结束指定的循环,而不是最近的。下图就只会输出“@外层循环0”
outer:
for(var i=0;i<5;i++){
console.log("@外层循环"+i};
for(var j=0;j<5;j++){
break outer;
console.log("内层循环:"+j)
}
}
- continue可以用来跳过当次循环,只能用在循环里面
- continue同样默认只会对他最近的循环起作用
break的应用(质数优化)
- console.time(“计时器的名字”)可以用来开启一个计时器,需要一个字符串作为参数,这个字符串将会作为计时器的标识
- console.timeEnd()用来停止一个计时器,需要一个计时器的名字作为参数;
- 可以通过Math.sqrt()对一个数进行开方,对于它开方以后,就没有因数了,有也只是重复的因数
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
//console.time("计时器的名字")可以用来开启一个计时器,需要一个字符串作为参数,这个字符串将会作为计时器的标识
console.time("test");
for (let i=2;i<=100;i++){
let flag = true;
for (let j=2;j<=Math.sqrt(i);j++){
if(i%j == 0){
//内层循环一旦进入判断里就已经证明i不是质数了,此时循环再执行已经没有意义了
//因此,使用break来终止内层循环,而外层循环继续
flag = false;
break;
}
}
if(flag){
console.log(i + '是质数');
}
}
// console.timeEnd()用来停止一个计时器,需要一个计时器的名字作为参数;
console.timeEnd("test");
</script>
</head>