1.创建变量的6种方式
变量(variable),它不是具体的值,只是一个用来存储具体指的容器或者代名词,因为它存储的值可以改变,所以称为变量。 基于ES语法,在JS中创建变量有以下方式。
- var (ES3)
- function (ES3) 创建函数(函数名也是变量,只不过存储的值是函数类型的而已)
- let (ES6)
- const (ES6) 创建的是常量
- import (ES6) 基于ES6的模块规范导出需要的信息
- class (ES6) 基于ES6创建类
/*
* 语法:
* var [变量名] = [值];
* let [变量名] = [值];
* const [变量名] = [值];
* function 函数名() {
*
* }
* ...
*/
var n = 13;
n = 15;
alert(n+10); // =>弹出来25,此时n代表15
const m = 100;
m = 200; // Uncaught TypeError:Assignment to constant variable.不能给一个常量重新的赋值(常量存储的值不能被修改,能被改变的就是变量了)
2.JS中的命名规范
- 严格区分大小写
- 遵循驼峰命名法: 按照数字、字母、下划线来命名(数字不能作为名字的开头),命名的时候基于英文单词拼接成一个完整的名字(第一个单词字母小写,其余每一个有意义的单词的首字母都大写)
- 不能使用关键字和保留字(在JS中有特殊含义的叫做关键词,未来可能会成为关键字的叫做保留字)
var n = 12;
var N = 13; //=>两个n/N不是同一个变量
var studentInfo / student_info / _studentInfo(下划线在前面的,都是公共变量) / $studentInfo(一般存储的是JQ元素) ...
语义化强一些
add / create / insert / delete / update / remove / info / detail / log
3.数据类型的分类
数据值是一门变成语言进行生产的材料,JS中包含的值有以下这些类型
- 基本数据类型(值类型)
- 数字 number
- 字符串 string
- 布尔 boolean
- null
- undefined
- 引用数据类型
- 对象 object
- 普通对象
- 数组对象
- 正则对象
- 日期对象
- ...
- 函数 function
- 对象 object
- ES6中新增加一个特殊的类型:Symbol,唯一的值
[基本数据类型]
var n = 13; // => 0 -13 13.2 数字类型中有一个特殊类型的值 NaN(not a number代表不是一个有效的数字,但是属于number类型的)
var s = ''; //=>"" '13' "{}" JS中所有用单引号或者双引号包裹起来的都是字符串,里面的内容是当前字符串中的字符(一个字符串由零到多个字符组成)
var b = true; //=>布尔类型只有两个值 true真 false假
[引用数据类型]
var o = {name: 'zfpx', age: 9}; //=>普通的对象:由大括号包裹起来,里面包含多组属性名和属性值(包含多组键值对) {} 空对象
var ary = [12,23,34,45]; //=>中括号包裹起来,包含零到多项内容,这种是数组对象。 [] 空数组
var reg = /-?(\d|([1-9]\d+))(\.\d+)?/g; //=>由元字符组成一个完整的正则
function fn () {
}
[Symbol]
创建出来的是一个唯一的值
var a = Symbol('珠峰');
var b = Symbol('珠峰');
console.log(a == b); // false
JS代码如何被运行以及运行后如何输出结果 [如何被运行]
- 把代码运行在浏览器中(浏览器内核来渲染解析)
- 基于NODE来运行(NODE也是一个基于V8引擎渲染和解析JS的工具) [如何输出结果]
- alert: 在浏览器中通过弹框的方式输出(浏览器提示框)
var num = 12;
alert(num); //window.alert
var str = 'zfpx';
alert(str);
基于alert输出的结果都会转化为字符串:把值(如果是表达式先计算出结果)通过toString这个方法转换成字符串,然后再输出
alert(1+1); // '2'
alert(true); //=> 'true'
alert([12,23]); // => '12,23'
alert({name:'xxx'}); //[Object Object] 为啥?
- confirm: 和alert的用法一致,只不过提示的框中有确定和取消两个按钮,所以它是确认提示框
var flag = confirm('确定要退出吗');
if (flag) {
//=>flag:true 用户点击的是确定按钮
} else {
// false 用户点击的是取消按钮
}
- prompt: 在confirm的基础上增加输入框
- console.log: 在浏览器控制台输出日志
- Elements: 当前页面中的元素和样式在这里都可以看到,还可以调节修改结构等
- Console: 控制台,可以在JS代码中通过.log输出到这里,也可以在这里直接的编写JS代码
- Sources: 当前网站的源文件都在这里 ...
- console.dir: 比log输出的更加详细信息一些(尤其是输出对象数据值的时候)
- console.table: 把一个JSON数据按照表格的方式输出 — ... (自己回去扩展更多的console输出的方法)
4.number数据类型详细解读(NaN和isNaN)
- number数字类型 NaN: not a number 但是它是数字类型的 isNaN: 检测当前值是否不是有效数字,返回true代表不是有效数字,返回false是有效数字
//=> 语法:isNaN([value])
var num = 12;
isNaN(num); //->检测num变量存储的值是否为非有效数字 false
isNaN('13') => false
isNaN('珠峰') => true
isNaN(true) => false
isNaN(false) => false
isNaN(null) => false
isNaN(undefined) => true
isNaN({age:9}) => true
isNaN([12,23]) => true
isNaN([12]) => false
isNaN(/^$/) => true
isNaN(function() {}) => true
// isNaN检测的机制
1、首先验证当前要检测的值是否为数字类型,如果不是,浏览器会默认的把值转换成数字类型
把非数字类型的值转换为数字
- 其他基本类型转换为数字:直接使用Number这个方法转换的
[字符串转数字]
Number('13') -> 13
Number('13px') -> NaN 如果当前字符串中出现任意一个非有效数字字符,结果为NaN
Number('13.5') -> 13.5 可以识别小数
[布尔转数字]
Number(true) -> 1
Number(false) -> 0
[其它]
Number(null) -> 0
Number(undefined) -> NaN
- 把引用数据类型转换为数字:先把引用值调取toString转换成字符串,然后再把字符串调取Number转换为数字
2、当前检测的值已经是数字类型,是有效数字返回false,不是返回true(数字类型中只有NaN不是有效数字,其余都是有效数字)
5.布尔类型和null以及undefined
布尔类型:只有两个值 true / false
如何把其他数据类型转换为布尔类型
- Boolean
- !
- !!
Boolean(1) -> true
Boolean(0) -> false
Boolean(-1) -> true
Boolean(NaN) -> false
!'珠峰' => 先把其它数据类型转换为布尔类型,然后再取反
!!null => 取两次反,等价于没取反,也就剩下转换为布尔类型了
规律:在JS中只有"0,NaN,"",null,undefined"这5个转换为布尔类型是false,其余都转换为true
null && undefined
都代表空
- null: 空对象指针
- undefined: 未定义
null一般都是意料之中的没有(通俗理解:一般都是人为手动的先赋值为null,后面的程序中我们会再次给他赋值)
var num = null; // =>null是手动赋值,预示着后面我会把num变量的值进行修改
...
num = 12;
undefined代表的没有一般都不是人为手动控制的,大部分都是浏览器自助为空(后面可以赋值也可以不赋值)
var num; // =>此时变量的值浏览器给分配的就是undefined
...
后面可以赋值也可以不赋值
6.对象数据类型的常规操作
普通对象
- 由大括号包裹起来的
- 由零到多对数星星和属性值(键值对)组成
属性是用来描述当前对象特征的,属性名是当前具备这个特征,属性值是对这个特征的描述(专业语法,属性名称为键[key],属性值称为值[value],一组属性名和属性值称为一组键值对)
var obj = {
name: "珠峰",
age: 9
}
//=>对象的操作:对键值对的增删改查
[获取]
语法:对象.属性名 / 对象[属性]
obj.name
obj['name'] 一般来说,对象的属性名都是字符串格式的(属性值不固定,任何格式都可以)
[增/改]
JS对象中属性名是不允许重复的,是唯一的
obj.name = 'zfpx'; //=>原有对象中存在name属性名,此处属于修改属性名
obj.sex = '男'; //=>原有对象中不存在sex,此处相当于给当前对象新增加一个属性sex
obj['age'] = 28; // =>修改属性
[删]
彻底删除: 对象中不存在这个属性了
delete obj['age'];
假删除: 并没有移除这个数属性,只是让当前属性的值为空
obj.sex = null;
在获取属性值的时候,如果当前对象有这个属性名,则可以正常获取到值(哪怕是null),但是如果没有这个属性,则获取的结果是undefined
obj['friends'] => undefined
[思考题]
var obj = {
name: '珠峰',
age: 9
};
var name = 'zhufeng';
console.log(obj.name); // '珠峰'
console.log(obj['name']); // '珠峰'
console.log(obj[name]); // =>此处的name是一个变量,我们要获取的属性名不叫name,是name存储的值'zhufeng' obj['zhufeng'] =>没有这个属性,属性值是 undefined
---------
'name' 和 name 的区别?
=> 'name'是一个字符串值,它代表的事本身
=> name是一个变量不是值,它代表的是本身存储的这个值
一个对象中的属性名不仅仅是字符串格式的,还有可能是数字格式的
var obj = {
name: '珠峰',
0: 100
};
obj[0] => 100
obj['0'] => 100
obj.0 => Uncanght SyntaxError: Unexpected number
-------
当我们存储的属性名不是字符串也不是数字的时候,浏览器会把这个值转换为字符串(toString),然后再进行存储
obj[{}]=300; =>先把{}.toString()后的结果作为对象的属性名存储起来 obj['[object Object]']=300
obj[{}] => 获取的时候也是先把对象转换为字符串 '[object Object]',然后获取之前存储的300
----
数组对象(对象是由键值对组成的)
var oo = {
a: 12
}
var ary = [12,23]; //=>12和23都是属性值,属性名呢?
通过观察结果,我们发现数组对象的属性名是数字(我们把数字属性名称为当前对象的索引)
ary[0]
ary['0']
ary.0 => 报语法错误
7.浅聊JS的运行机制(堆栈内存和不同数据类型操作方式)
var a = 13;
var b = a;
b = 13;
console.log(a);
var obj1 = {n: 100};
var obj2 = obj1;
obj2['n'] = 200;
console.log(obj1.n);
/**
* 浅分析JS的运行机制
* 1、当浏览器(它的内核\引擎)渲染和解析JS的时候,会提供一个供JS代码运行的环境,我们把这个环境称之为"全局作用域(global scope)"
* 2、代码自上而下窒息性(之前还有一个变量提升阶段)
* var a = 12;
* 1)首先开辟一个空间存储12
* 2)在当前作用域下声明一个变量a (var a)
* 3)让声明的变量和存储的12进行关联(把存储的12赋值给a=>赋值操作叫做定义)
*
* 基本数据类型(也叫做值类型),是按照值来操作的:把原有的值复制一份,放到新的空间或者位置上,和原来的值没有关系
*
* => 引用数据类型的值不能直接存储到当前的作用域下(因为可能存储的内容过于复杂),我们需要先开辟一个新的空间(理解为仓库),把内容存储到这个空间中
* var obj1 = {n: 100};
* 1)首先开辟一个新的内存空间,把对象中的键值对依次存储起来(为了保证后面可以找到这个空间,此空间有一个16进制的地址)
* 2)声明一个变量
* 3)让变量和空间地址关联在一起(把空间地址赋值给变量)
*
* 引用类型不是按照值来操作,它操作的是空间的引用地址:把原来空间的地址赋值给新的变量,但是原来的空间没有被克隆,还是一个空间,这样就会出血线多个变量关联的事相同的空间,相互之间就会存在影响了。
* 栈内存:本身就是一个供JS代码执行的环境,所有的基本类型值都会直接在栈内存中开辟一个位置进行存储
* 堆内存:用来存储引用类型中的信息值的,对象存储的是键值对,函数存储的是代码字符串
*/
var obj = {
n: 10,
m: obj.n * 10
}
console.log(obj.m); //=>Uncaught TypeError: Cannot read property 'n' of undefined
/**
* 1、形成一个全局作用域(栈内存)
* 2、代码自上而下执行
* 1.首先开辟一个新的堆内存(AAAFFF111),把键值对存储到堆内存中
* n:10
* m:obj.n*10 =>obj.n 此时堆内存信息还没有存储完成,空间的地址没有给obj,此时的obj是undefined, obj.n<=>undefined.n
*/
var ary1 = [3,4];
var ary2 = ary1;
ary2[0] = 1;
ary2 = [4,5];
ary2[1] = 2;
ary1[1] = 0;
console.log(ary1,ary2); // [1, 0], [4, 2]
8.JS中的判断操作语句
- if / else if / else
var num = -6;
if (num>10) {
num++; // num=num+1 num+=1 在自身的基础上累加1
}else if (num>=0 && num<=10) {
num--;
}else{
num+=2;
}
console.log(num); // -4
只要有一个条件成立,后面不管是否成立的条件,都不再判断执行了
var num = 10;
if (num>5) {
num+=2;
}else if(num>8) {
num+=3;
}else{
num+=4;
}
console.log(num); // 12
关于条件可以怎么写?
// >= <= ==
if (0) {
//=>不管你在条件判断中写什么,最后总要把其计算出true/false来判断条件是否成立(把其他类型的值转换为布尔类型,只有 0/NaN/''/null/undefined 是false,其余都是true)
}
if('3px'+3) {
//=>在JS中,+ - * / % 都是数学运算,除 + 以外,其余运算符在运算的时候,如果遇到了非数字类型的值,首先会转换为数字类型(Number),然后再进行运算
}
//=>+在JS中出了数学相加,还有字符串拼接的作用(如果运算中遇到了字符串,则为字符串拼接,而不是数学相加)
var num = parseInt('width:35.5px');
if(num==35.5) {
alert(0);
}else if(num==35) {
alert(1);
}else if(num==NaN){
alert(2);
}else if(typeof num=='number') {
//=>先算typeof num
//=>再做比较
alert(3); //=>alert输出的都是字符串格式的 ‘3’
}else{
alert(4);
}
9.三元运算符和switch case
1、三元运算符 语法:条件?成立做的事情:不成立做的事情;<=> 相当于简单的if/else判断
var num = 12;
if (num>10) {
num++;
}else{
num--;
}
// num>10?num++:num--;
特殊情况
//=>如果三元运算符中的某一部分不需要做任何的处理,我们用null/undefined/void 0...占位即可
var num = 12;
num>=10?num++:null;
//=>如果需需要执行多项操作,我们把其用小括号括起来,每条操作语句用逗号分隔
num = 10;
num>=10?(num++,num*=10):null;
[思考题]:改成三元运算符
var num = 12;
if (num>0) {
if(num<10) {
num++
}else{
num--;
}
}else{
if(num==0) {
num++;
num=num/10;
}
}
2.switch case JS中的一种判断方式
var num = 12;
if (num==10) {
num++;
}else if(num==5){
num--;
}else{
num=0
}
//=>改成switch case
switch(num) {
case 10:
num++;
break;
case 5:
num--;
break;
default:
num=0;
}
//=>switch case 应用于变量(或者表达式等)在不同值的情况下的不同操作,每一种case结束后都要加break(结束整个判断)
switch case中每一种case情况的比较都是基于"==="绝对相等来完成的
'10'==10 =>true 相等比较,如果等号左边两边的类型不一样,首先会转换为一样的额数据类型,然后再进行比较
=>当前案例中,就是把字符串'10'转换为数字了,然后再比较的
'10'===10 绝对比较,如果两边的数据类型不一样,则直接不相等,它要求类型和值都完全一样才会相等(真实项目中为了保证代码的严谨性,我们应该更多使用绝对比较)
var num = 12;
switch(num) {
case 10:
case 5:
num--;
break;
default:
num=0;
}
//=>不加break,后面的条件不管是否成立,都会被执行;利用此机制,我们可以完成一些特殊的处理,例如:如果num等于10和等于5都要做同一件事情,那么我们写在一起,不用加break即可
10.for循环的基础运行机制
1、for循环
作用:按照一定的规律重复去做某件事情,此时我们就需要使用循环来处理了。
var ary = [12,23,34];
/**
* 循环输出数组中的每一项内容
*/
for (var i = 0; i < ary.length; i++) {
//=>第一次循环:i=0 i<3 ... i=1
//=>第一次循环:i=1 i<3 ... i=2
//=>第一次循环:i=2 i<3 ... i=3
//=>第一次循环:i=3 i<3 循环结束(本次没有循环)
console.log(ary[i]);
}
/**
* for循环的语法组成
* 1.定义初始值 var i = 0;
* 2.设定循环成立的条件(条件成立循环继续,不成立循环结束) i < ary.length
* 3.条件成立会执行循环体中的内容(大括号包裹的就是循环体)
* 4.执行步长累加的操作
*/
// 倒着输出 34 23 12
// =>ary.length-1:当前数组中最后一项属性名(索引)
for (var i = ary.length - 1;i >= 0;i--) {
console.log(ary[i]);
}
// 输出数组中的内容:输出奇数项的内容
for (var i = 0; i < ary.length; i++) {
if (i % 2 === 0) {
console.log(ary[i]);
}
}
for (var i = 0; i < ary.length; i+=2) {
console.log(ary[i]);
}
在for循环的循环体中,经常出现两个常用的关键字:
/**
* 1.continue:继续
* 2.break: 中断或者结束
*/