这是JavaScript
HTML描述页面的结构,CSS展现页面的样式,JS在页面中描述行为、控制交互。
JavaScript里没有Java,就像老婆饼里没有老婆。
JavaScript是解释型语言,既是前端语言,又是后端语言,当它运行在浏览器中时是前端语言,后端语言运行在服务器中也称为服务端语言,NodeJS可以让JS运行在服务端。
JavaScript基础由三部分组成,ECMAScript是语法,DOM和BOM是浏览器提供的API:
- ECMAScript: JavaScript的语法标准,至少要学习到ES6,它规定了JS最基础的语句、变量、函数、运算等等。
- DOM: 文档对象模型(Document Object Model),JS操控网页元素的API。
- BOM: 浏览器对象模型(Browser Object Model),JS操控浏览器的API。
使用JS
- 行内: 写在标签属性中。
<input type="button" value="点我" href="javascript:;" onclick="alert('你好')" />- 内嵌: 写在
<script></script>标签中。
<script type=”text/javascript”> alert('你好');</script>- 外链: 在
<script></script>标签的src属性中写上js文件的链接。
<script type="text/javascript" src="main.js"></script>执行顺序
浏览器默认从上至下解析网页,JS的加载默认会阻塞网页的解析,通过JS操控网页元素,需待网页解析完后执行、写在html的最后或写在对应元素后,否则就可能因为DOM树不完整,要操控的对象还未被加载而报出undefined错误。
<!-- 不等待后续网页的解析,到此就加载JS并执行 --><script src="main.js"></script><!-- 网页的解析与JS的加载异步,但JS在网页解析完后执行 --><script defer src="main.js"></script><!-- 网页的解析与JS的加载异步,JS加载完后立即执行 --><script async src="main.js"></script>//待网页解析完、网页中所有资源(图片、css)都加载完毕,执行其中的代码window.onload = function () { //js代码 alert('你好');}输出语句
console.log(): 在控制台输出内容
console.log('日志'); //普通打印console.warn('警告'); //警告打印console.error('出错了'); //错误打印alert(): 警告对话框confirm(): 确认对话框,返回true或false <input type="button" value="测试" href="javascript:;" onclick="var a="confirm("'确认吗');if(a){alert('你确认了')}else{alert('未确认')}" />
var a = confirm('确认吗');if(a){ alert('你确认了')}else{ alert('未确认')}prompt(): 输入对话框,返回输入内容或空字符串,点取消返回NULL <input type="button" value="测试" href="javascript:;" onclick="var a="prompt("'输入内容');if(a){alert('你输入了:'+a)}else if(a==''){alert('你没输入任何东西')}else{alert('取消')}" />
var a = prompt('输入内容');if(a){ alert('你输入了:'+ a)}else if(a==''){ alert('你没输入任何东西')}else{ alert('取消')}常量、变量、标识符
数字常量、字符串常量、布尔常量
console.log(123); //123是数字console.log('123'); //'123'是字符串,''空字符串console.log('你好'); //''包裹起来的都是字符串if(true){ //true、false布尔常量 console.log('true');}自定义常量const
const a = '123'; //定义a为常量a = '321'; //不允许修改常量const a = '321'; //不允许重新声明定义变量var、let(ES6)
var a = '123';let b = 321;//重新定义var a = '321'; //var允许重新定义let b = 123; //let不允许重新定义//不允许var和let之间重新定义var c = 123;let c = 123;var可以在声明前使用,值为undefined,而let必须先声明再使用。
var是函数作用域,let是块作用域。
标识符(一切可自主命名的,如变量名、函数名)命名规则:
- 区分大小写
- 只能由字母(A-Z、a-z)、数字(0-9)、下划线(_)、美元符( $ )组成
- 不能以数字开头、不允许出现空格
- 不能出现中划线 -
数据类型
JavaScript是弱类型语言(动态语言),无需声明变量的类型,在程序运行过程中,会根据等号右边的值自动确定类型。
var a = 123;console.log(typeof a);//输出numbera = '123'//强制将变量a数据类型转换为字符串console.log(typeof a);//输出stringa = Number(a);//强制将字符串'123'转换为数字123console.log(a);//输出123JS中数据类型分为基本数据类型和引用数据类型
- 基本数据类型(值类型): String字符串、Number数值、BigInt(ES6)大型数值、Boolean布尔值、Null空值、Undefined未定义、Symbol(ES6)。
- 引用数据类型(引用类型):Object 对象(除了基本数据类型之外,都可称之为Object类型)。
基本数据类型传数值,引用数据类型传地址。
var a = 23;var b = a;//将a的值23传给ba++;console.log(a); //24console.log(b); //23,改变a的值不影响bvar a = new Object();//a、b都是引用数据类型b.name = '123';var b = a;//传的是a的地址,a和b是同一个东西a.name = '321';console.log(a.name); //321console.log(b.name); //321,修改a对象的属性也会修改bJS中,所有的变量都保存在栈内存中的。
基本数据类型直接保存在栈内存中。值与值之间独立存在。
对象Object保存在堆内存中,创建一个新的对象,在堆内存中开辟一个新的空间,变量在栈内存中保存了对象的内存地址(对象的引用)。
String字符串
字符串是双引号和单引号中的文本,不同类型引号可以嵌套使用。
var a = '123';console.log(a);//123var b = '1"2"3';console.log(b);//1"2"3var c = '12 3';console.log(c);//12 3不忽略连续多个空格加入字符串进行拼接,可以被同化为字符串
console.log(typeof(123+''));//string转义字符: \
- 双引号:
\",单引号\' \\表示\\r回车,\n换行\t缩进\b空格
字符的数量就是字符串的长度,获取字符串的长度.length:
var a = "abc";console.log(a.length);//3a = "你好";console.log(a.length);//2使用 + 进行字符串拼接:
var a = "你好"+"世界";console.log(a);//你好世界a = "你好"+ 1;console.log(a);//你好世界1a = "你好"+ null;console.log(a);//你好nulla = "你好"+ true;console.log(a);//你好trueES6新增模板字符串:**,可以使用`${变量名}`将其嵌入字符串,使用时需要反引号 ** 包裹。
var a = 2022;var b = '2023';console.log(`去年是${a},今年是${b}`); //去年是2022,今年是2023,注意使用反引号模板字符串中可以换行,不忽略连续的多个空格,保留原有格式。
可以调用函数:
function getHtml() { return `<div> <span>1</span> <span>2</span> <span>3</span></div>`;}console.log(`1${getHtml()}2`);/*1<div> <span>1</span> <span>2</span> <span>3</span></div>2*/可以嵌套使用,进行运算:
var a = 1;var b = 2;console.log(`${a+`${b}`}`);//12console.log(`${a+b}`);//3Number数值型
JS中整数和浮点数等所有的数值都是Number类型。
var a = 1;var b = 1.2;console.log(typeof a);//numberconsole.log(typeof b);//number数值范围:
console.log(Number.MAX_VALUE);//1.7976931348623157e+308console.log(Number.MIN_VALUE);//5e-324数值变量超过了最大值,则会返回Infinity,Infinity也是一种数值,代表无穷大。
var a = Number.MAX_VALUE;var b = Number.MIN_VALUE;console.log(a*2);//Infinityconsole.log(b/2);//0console.log(a*(-2));//-Infinityconsole.log(typeof Infinity);//numberNaN是一个特殊的数字,表示不是数值(Not a Number),当运算不出数值时就会返回NaN。
console.log(typeof NaN);//numberconsole.log('abc' / 2);//NaNconsole.log('a' * '2');//NaNUndefined和任何数值计算的结果均为NaN。NaN与任何值都不相等,包括NaN本身。
console.log(undefined + 1);//NaNconsole.log(null + 1);//1console.log(NaN==NaN);//false隐式转换,当有字符串介入的运算,且字符串可被转换为数值,除了+表示字符串连接,其余都会自动将字符串转为数值后进行运算。
console.log('1' + '2');//12console.log('1' * '2');//2console.log('1' / 2);//0.5console.log('1' - 2);//-1console.log('1' + '2' * '3');//16浮点数的运算精度并不足够准确,当需要进行高精度运算时,最好引入可靠的数学库。
var a = 0.1 + 0.2;console.log(a); //0.30000000000000004Null与Undefined
undefined实际上是由null衍生出来的。
undefined表示未定义,应该有值但还未赋值,连null这个值都没有赋予给它。 null代表空值,本身是一个具体的值或空引用。
null和undefined值上相等,但类型不一样。 null是引用类型Object,代表空对象,存的地址为空,而undefined的类型是undefined,代表未定义的值。
console.log(null == undefined);//trueconsole.log(null === undefined);//false
console.log(typeof null);//objectconsole.log(typeof undefined);//undefinednull转为数值是0,undefined转为数值是NaN。 任何值和null运算,null可看做0。任何数据类型和undefined运算,结果都是NaN。
console.log(Number(null));//0console.log(Number(undefined));//NaN
console.log(null+1);//1console.log(undefined+1);//NaN出现undefined的情况:
- 变量被声明了,但是没有被赋值
- 变量未声明(未定义)时
- 调用函数时,未传参
- 函数无返回值时
- 访问一个对象中没有的属性
console.log(a);//undefinedvar a;console.log(a);//undefined
function Fun(item) { console.log(item);}console.log(Fun());//undefinedFun();//undefined出现null的情况:
- 访问一个不存在的dom节点
- 作为对象原型链的终点出现
数据类型转换
变量的数据类型转换:将一种数据类型转换为另外一种数据类型。(通常在基本数据类型中互相转换)
- 显式类型转换
toString()转换为字符串String()强制转换为字符串Number()转为数值,保留小数parseInt()字符串转整数,直接舍去小数部分parseFloat()在parseInt()的基础上可以获得小数部分Boolean()- 隐式类型转换
isNaN()- 自增/自减
- 正号/负号
- 加号(字符串拼接)
- 其它数值运算符
- 逻辑运算符:会先非布尔值转换为布尔值,再运算
- 关系运算符:运算结果都是布尔值
转为字符串
toString():
var a = 123;console.log(a.toString());//"123"a = true;console.log(a.toString());//"true"a = [1, 2, 3];console.log(a.toString());//"1,2,3"a = { name: 'qx', age: 18 };console.log(a.toString());//"[object Object]"null和undefined这没有toString()方法,调用会报错
var a = null;console.log(a.toString());//Cannot read properties of null (reading 'toString')a = undefined;console.log(a.toString());//Cannot read properties of null (reading 'toString')Number类型的变量,在调用toString()时,可以传入一个整数,把数字转换为指定的进制,默认转换为10进制。
var a = 8;a = a.toString(2); //转换为二进制console.log(a); //"1000"console.log(typeof a);//string数字不允许直接调用toString()
1.toString()//不允许,会把.看成小数点,小数点后面出现非数字是不允许的1..toString()//允许(1).toString()//允许使用String()强制转换为字符串。
对于非null和undefined的数据类型而言,实际上就是调用toString()。
对于null和undefined,直接转换为"null"和"undefined"。
var a = 123;console.log(String(a));//"123"a = null;console.log(String(a));//"null"a = undefined;console.log(String(a));//"undefined"字符串拼接,隐式转换:
var a = 123;console.log(a+'');//"123"转为数值
Number()转为数值类型
- 字符串转数字
- 字符串中是纯数字,直接将其转换为数字
- 空字符串或全是空格,转换为0
- 字符串中包含了非数字的内容,转为NaN
- 布尔值转数字:true --> 1,false --> 0
- null --> 0,undefined --> NaN
加上正负号隐式转换。规则和Number()一样,但是改变正负性,0也会带上负号:
var a = '123';console.log(+a); //123console.log(-a); //-123console.log(typeof +a);//numbera = nullconsole.log(+a); // 0console.log(-a); // -0parseInt() 字符串转整数,布尔、null等非字符串、非数值类型都转为NaN,逐个字符转,碰见非数字字符就停止,没有提取到数值,就返回NaN。
parseInt('123abc'); //123parseInt('abc123'); //NaNparseInt(''); //NaNparseInt(' '); //NaNparseInt(null); //NaNparseInt(undefined); //NaNparseInt(true); //NaNparseInt()会自动截断、舍弃小数,而Number()不会。
var a = parseInt('5.1') + parseInt(5.9);console.log(a);//10a = Number('5.1') + Number(5.9);console.log(a);//11a = parseInt(5.1 + 5.9);console.log(a);//11parseInt()可以多带一个进制参数,把数值看成对应进制,再转成10进制返回。无论parseInt()里面的进制参数是多少,最终的转换结果是十进制。
var a = parseInt('101', 2);console.log(a);//5 二进制101就是十进制的5
a = parseInt('3', 2);console.log(a);//二进制中没有3,所以转换失败返回NaNparseFloat() 字符串转小数,与parseInt()相似。
parseFloat('123.321abc'); //123.321parseFloat('12.1a3.321'); //12.1parseFloat('12.13.321'); //12.13转为Boolean
任何数据类型都可以转为 Boolean 布尔型。
- 数值型: 0 和 NaN的转为 false,其它都是 true
- 字符串: 空串转为 false,其它都是 true。全是空格的字符串,转换结果也是 true。"0"也是 true。
- null 和 undefined 都转为 false
- 引用数据类型都转为 true,因为地址永不为空或0。空数组[]和空对象{},也是 true
var a;Boolean(a);//false,a未赋值,undefineda = '';Boolean(a);//falsea = [];Boolean(a);//truea = {};Boolean(a);//true使用!!或!显式转换为 Boolean 类型:
var a = 1;a = !aconsole.log(a);//falsea = !!2;console.log(a);//trueisNaN()判断是否是非数值类型,任何不能直接转为数值类型的数据类型都可以让这个函数返回true
isNaN('123');//可以转为123,返回falseisNaN(null);//转为0,falseisNaN('123abc');//trueisNaN(undefined);//true运算符和运算
各种编程语言的运算符功能都大差不差,只介绍JS中比较特殊的运算或特例。
浮点数值的最高精度是 17 位小数,会有丢失精度的风险,不要直接判断两个浮点数是否相等
Boolean + 数字 = 数字,true按1来算,false按0。
null + 数字 = 0 + 数字
undefined + 数字 = NaN
任何值和 NaN 运算的结果都是 NaN
任何非数值类型进行除加法以外的运算-、*、/、%时,都会自动用Number()转成数值类型再参与运算
true + 1; //2null + 1; //1var a = 2 - '1'; //1var a = '2'/'1'; //2非布尔值进行与或运算(&&、||)时,会先将其转换为布尔值,然后再运算,但返回结果是原值。
**与运算 &&**的返回结果:从左到右依次运行语句,找到第一个为 false 的值,返回原值,不再往后执行。如果所有的值都为 true,则返回最后一个值。
var a = '' && 123;console.log(a);//'',空字符串转为布尔型为false,只执行第一条语句并返回原值var a = [] && 0;console.log(a);//0,[]转为布尔型为true,直接返回第二个语句的值var a = "0" && 0 && 1;console.log(a);//0**或运算 ||**的返回结果:从左到右依次运行语句,找到第一个为 true 的值,返回原值,不再往后执行。如果所有的值都为 false,则返回最后一个值。
var a = '' || null;console.log(a);//nullvar a = 0 || [];console.log(a);//[]var a = "0" || 0 || 1;console.log(a);//"0"比较运算符 >、<、==、!= 等,得到的结果都是布尔值:要么是 true,要么是 false,非数值进行比较,会将其转换为数值类型。
特殊情况:如果参与比较的都是字符串,则不会将其转换为数字进行比较,比较的是字符串的Unicode编码。 比较字符编码时,从左到右逐位进行比较,一样大则继续比较下一位,直到比较出大小。
console.log('100' > 9 );//true,将'100'转为数值100进行比较console.log('100' > '9' );//false,两个字符串逐位比较,9比1大,返回false== 、=== ==进行比较时,会做隐式转换,将不同的数据类型,转为相同类型进行比较,而全等符号===不会进行转换,不同类型的数据比较一定是false。
console.log('1' == 1); //trueconsole.log('1' === 1); //false
console.log(1 == true); //trueconsole.log(1 === true); //false
console.log(undefined == null); //trueconsole.log('1a' > 1); // false。'1a'转成NaN
//NaN不和任何值相等,包括它本身console.log(NaN == NaN); //falseconsole.log(NaN === NaN); //falsenull与数字进行比较有一个Bug,不必在意,当特性就行:
console.log(null < 0); //falseconsole.log(null == 0); //falseconsole.log(null > 0); //false
console.log(null <= 0); //true。这是一个bugconsole.log(null >= 0); //true。同上日期大小比较
var date1 = new Date(2023, 3, 28)console.log(date1);//Fri Sep 08 2023 00:00:00 GMT+0800 (中国标准时间)var date2 = '2023-03-27';var date3 = '2023/03/29';console.log(date1 > date2);//false,date1和date2字符串格式很不相同,比较无意义console.log(date3 > date2);//true,格式基本相同,分割位置一样,字符串逐位比较大小if和switch
这部分各大语言也大差不差,只记录值得注意的点。
case的判断逻辑是**===,不是==**
switch中的default无论放到什么位置,都会等到所有case都不匹配再执行,但一般放在最后
当case或default匹配到一个值后,会执行后续所有的case,除非遇到break或执行到switch的末尾。
循环
这部分各大语言也大差不差,只记录值得注意的点。
break会立即终止离它最近的循环语句,continue跳过当次循环,继续下一次循环。
可以为循环语句创建一个label,来标识当前的循环。使用break、continue语句时,break label将会结束指定的循环,而不是最近的。
one: for (var i = 0; i < 100; i++) { for (let j = 0; j < 100; j++) { if(i>j) { break one; } }}console.log(i);//1
评论