JavaScript
JS:轻量级的客户端脚本编程语言
书籍:
1.编程语言
HTML+CSS是标记语言。
编程语言是具备一定逻辑的,拥有自己的编程思想(面向对象编程[OOP],面向过程编程)
- 面向对象
- C++
- JAVA
- PHP
- C#(.NET)
- JS
- …
- 面向过程
- C
2.目前的JS是基于NODE可以做服务器端程序,所以JS是全栈编程语言。
3.JS 学习
- ECMAScript(ES): JS核心语法
- DOM: document object model 文档对象模型,提供各种API(属性和方法),让JS可以获取或操作页面中的HTML元素(DOM和元素)
- BOM: browser object model 浏览器对象模型,提供各种API,让JS操作浏览器
4.ECMAScript
它是JS语法规划,规定:JS中的变量、数据类型、语法规范、操作语句、设计模式等等
- 版本
- 1997 ES1.0
- 1998 ES2.0
- 1999 ES3.0(广泛应用)
- 2000 ES4(夭折)
- 2015/6 ES6
- …
变量(varibale)
它不是具体的值,只是一个用来存储具体值的容器或者代名词。存储的值可以改变,即变量。
基于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);
const m = 100;
m = 150; // => Uncaught TypeError: Assignment to constant variable. 不能给一个常量重新赋值,常量存储的值不能被修改。
创建变量,命名的时候要遵循一些规范
- 严格区分大小写
var n = 12;
var N = 13; //=> 两个N不是同一个变量
- 遵循驼峰命名法:按照数字、字母、下划线或者$来命名,数字不能作为名字的开头,命名的时候基于英文单词组成一个完整的名字,第一个单词字母小写,其余每一个有意义的单词的首字母都大写。一般“ _ ” 在前的,都是公共变量,如:
_studentInfo
- 不能使用关键字和保留字
数据类型
数据值是一门编程语言进行生产的材料,JS中的数据类型:
- 基本数据类型/值类型
- 数字number
- 字符串string
- 布尔boolean
- null
- undefined
- 引用数据类型
- 对象object
- 普通对象
- 数组对象
- 正则对象
- 日期对象
- …
- 函数function
- 对象object
- Symbol (唯一的值,ES6中新增加的一个特殊的类型)
[基本数据类型]
var n = 13; //=>0 -13 13.2 数字类型中有一个特殊的值NaN(not a number 表示不是一个有效的数字,但是属于number类型)
var s = ''; //=> "" '13' “{}”,一个字符串由零到多个字符串组成
var b = true; //=> 布尔 true真 flase假
[引用数据类型]
var o = {name: 'serendity',age: 10 }; //=> 普通对象:由大括号包括起来。里面包含多组属性名和属性值/包含多组键值对,{} 空对象
var ary = [12,23,20, 21]; //=>数组对象:中括号包裹,包含零到多项内容 [] 空数组
var reg = /-?(\d|([1-9]\d+))(\.\d+)?/g; //=>正则对象:由元字符组成一个完整的正则 。验证是否为有效数字 ;至少包含一个字符,没有空正则
function fn() {
}
[Symbol] 创建出来的是一个唯一的值/没有其他的与它相等
var a = Symbol(‘n’)
var b = Symbol(‘n’)
a===b // => false
const a = Symbol(‘n’); // => 只是唯一的并且不可以被更改,用const声明。
扩展: JS代码如何被运行以及运行后如何输出结果
[如何被运行]
- 把代码运行在浏览器中/浏览器内核来渲染解析
- 基于NODE来运行/Node也是一个基于V8引擎渲染和解析JS的工具,注:node不是一种语言,是渲染JS的工具或平台。
[如何输出结果]
- alert: 在浏览器中通过弹窗的方式输出/浏览器提示框
window.alert();
alert(1+1); // => '2',基于alert输出的结果都会转换为字符串:把值(如果是表达式先计算出结果)通过toString这个方法转换为字符串,然后输出
alert(true); // => 'true'
// alert({name:'xxx'}); => '[object object]'
// {name:'xxx'}.toString =>'[object object]' 为什么?
// 对象.toString后的结果是object object.
- confirm: 和alert的用法一致。只不过提示框中有确定和取消两个按钮。 即确认提示框。
var flag = confirm('确定要退出吗?');
if(flag){
//=>flag:true 用户点击确定
}else {
//=>flag:flase 用户点击取消
}
- prompt: 在confirm的基础上增加输入框 点击取消 输出null, 确定 输出空字符串
- console.log: 在浏览器控制台输出日志
- Elements
- Console: 控制台
- Sources: 网站源文件
- …
- console.dir: 比log输出的更加详细一些,尤其输出对象数据值时
- console.table: 把JSON数据按照表格的方式输出
- …更多console输出方法
数据类型的详细刨析
number 数字类型
- number 数字类型
NaN : not a number 但是它是数字类型的
isNaN: 检测当前的值是否不是有效数字 返回 true 表示不是有效数字,flase 是有效数字
// = > isNaN ([value])
var num = 12
isNaN(num); // = > 检测 num 变量存储的值是否为有效数字 flase
isNaN('13'); = > false
isNaN('num'); = > true
isNaN(true); = > false
isNaN(false); = > 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('13.5.0') -> NaN
[布尔转数字]
Number(true) -> 1
Number(false) -> 0
[其他]
Number(null) -> 0
Number(undefined) -> NaN
- 把引用数据类型转换为数字: 先把引用值调取 toString 转换为字符串,然后再把字符串调取 Number 转换为数字。
[对像转数字]
所有对象 toString() => '[object object]'
({})).toString() -> '[object object]' - > NaN
[数组转数字]
([12,23]).toString() -> '12,23' - > NaN
([12]).toString() -> '12' - > 12
[函数转数字]
(function() {}).toString() -> "function() {}" -> NaN
[正则]
/^$/.toString() -> '/^$/' - > NaN
Number('') - > 0
[].toString() -> ''=> isNaN([]) => false
2. 当前值已经是数字类型,是有效数字返回 false,不是返回 true (数字类型中 只有 NaN 不是有效数字 其余都是有效数字)
*/
- parseInt / parseFloat
等同于 Number ,也是为了把其他类型的值转换为数字类型
和 Number 区别在于字符串的转换分析
Number: 出现任意非有效数字字符 结果就是 NaN;
parseInt: 把一个字符串中的整数部分解析出来
parseFloat:把一个字符串中的小数(浮点数)部分解析出来
parseInt('13.5px') => 13
parseFloat('13.5px') = > 13.5
parseInt('width:13.5px') => NaN 从字符串最左边字符串开始查找有效数字字符并且转换为数字,一旦遇到一个非有效数字字符,查找结束。
- NaN 的比较
NaN: 不是一个数,可以是其他任何东西
NaN == NaN => false NaN 和谁都不相等 包括自己
思考: 有一个变量 num ;存储的值不知道,检测是否为一个有效数字,一下方案是否可以
if(Number(num) == NaN) {
alert('不是')
}
NaN 和谁都不相等,假设 num 不是有效数字,=> NaN; 此条件永远不成立,即使 num 确实不是有效数字。
// 有效数字 检测只有这一种方案
if(isNaN(num)) { // true 不是有效数字
alert('不是')
}
布尔类型
只有两个值: true / false
- 如何把其他数据类型转换为布尔类型?
- Boolan(); 数字中除了 0 和 NaN 是 false 其他都是 true
- !
- !!
Boolean(1) = > true
Boolean(0) = > false
Boolean(-1) = > true
Boolean(NaN) = > false
!'Serendipity' // 先把其他数据类型转换为布尔类型 然后取反 !true => false
!!'' // 先把其他数据类型转换为布尔类型 然后取两次反,等价于没取反,即剩下布尔值 => false
规律: 在 JS 中只有“ 0 / NaN / 空字符串 / null / undefined ”这五个值转换为布尔类型为 false,其余都转换为 true
null 和 undefined
null 和 undefined 都代表空或没有
- null: 空对象指针
- undefined: 未定义
- null 和 undefined 的区别
- null: 一般独使意料之中的没有一般都是手动的先赋值为 null,后面程序会再次赋值
- undefined: 意料之外的没有,一般都不是人为手动控制,大部分都是浏览器自主为空,后面赋值也可以不赋值
Object 对象数据类型
普通对象
- 由大括号包裹起来
- 由零到多组属性名和属性值(键值对)组成
属性是用来描述当前对像特征的,属性名是对当前具备这个特征,属性值是对这个特征的描述(专业语法:属性名称为键[key],属性值称为值[value],一组属性名和属性值称为一组键值对)
var obj = {
name: 'serendipity'
age: 9
}
// => 对象的操作: 对键值对的增删改查
[获取]
语法: 对象.属性名 / 对象[属性名]
obj.name
obj['name'] 一般来说,对象的属性名都是字符串格式的。(属性值不固定,任何格式都可以)
[增/改]
JS的一个对象中属性名是唯一的,不允许重复
语法:对象.属性名 = xxx / 对象[属性名] = xxx
obj.name = '某某某某'; // => 原有对象中存在 name 属性,此处属于修改属性值
obj.sex = '男'; // => 原有对象中不存在 sex 属性,此处属于增加属性
obj['age'] = 23;
[删]
彻底删除:对象中不存在这个属性
delete obj['age'];
假删除:并没有移除这个属性,只是让当前的属性值为空
obj.sex = null;
在获取属性值的时候,如果当前对象有这个属性名,则可以获取到值(哪怕是 null ),如果当前对象有这个属性名,则可以获取到值(哪怕是 null )如果当前对象没有有这个属性名,则获取结果是 undefined;
思考题:
var obj = {
name: 'serendipity'
age: 9
};
var name = 'cherish';
obj.name = > serendipity 获取的是 name 属性的值
obj['name'] = > serendipity 获取的是 name 属性的值
obj.[name] = > undefined 此处的 name 是一个变量 我们获取的属性名不叫做 name ,是 name 存储的值 ‘cherish’,
obj['cherish'] = > 没有这个属性 ,undefined
----
'name' 和 name 的区别
= > 'name' 是一个字符串值 代表的是本身
= > name 是一个变量 不是值 代表本身存储的这个值
[一个对象中的属性名不仅仅是字符串格式,还可能是数字格式的。遇到]
var obj = {
name: 'serendipity'
0: 100
}
obj[0] => 100
obj['0'] => 100
obj.0 => 报错 SyntaxError 语法错误
----
当我们存储的属性名不是字符串也不是数字的时候,浏览器会把这个值转换为字符串(toString),然后再进行存储
obj.[{}] = 300; => 先把 ({}).toString() 后的结果作为对象的属性名存储起来 obj.['[object object]'] = 300;
// 获取的时候
obj.[{}]; => 获取的时候也是先把对象转化为字符串'[object object]' ,然后获取之前存储的 300;
obj[1] '1': 100
----
数组对象(对象由键值对组成)
var oo = {
a : 12;
}
// 数组也是对象
var arr = [12,23] // 12 和 23 都是属性值,属性名呢?
通过观察结果: 数组对象的属性名是数字,(我们把数字属性名称为当前对象的索引)
arr[0] => 12;
arr['0'] => 12;
arr.0 => 报错 SyntaxError 语法错误
arr.length
arr['length']
[],的语法不支持直接添加属性名 如:[age:12]
数组也是对象,对象所拥有的操作,都可以运用到数组,可以添加非数字索引,数组的索引也是属性名,但是比较特殊可以递增。所有的对象 object 都可以运用对象的操作 函数也是对象
浅分析 JS 的运行机制
var a = 12;
var b = a;
b = 13;
console.log(a); // => 12
var obj1 = {n: 100}
var obj2 = obj1;
obj2['n'] = 200;
console.log(obj1.n); // => 200
/**
* 浅分析 JS 运行机制
* 1.当浏览器(他的内核 / 引擎)渲染和解析 js 的时候,会提供一个供 js 代码运行的环境我们把这个环境称为全局作用域(global/windowscope)
*
* 2.代码自上而下执行(之前还有一个变量提升阶段)
* = > 基本数据类型的值会存储再当前作用域下
* var a = 12 ;
* 1)首先开辟一个空间(栈内存空间)存储 12
* 2)在当前作用域中声明一个变量 a
* 3)让声明的变量和存储的 12 进行关联(把存储的 12 赋值给 a =>赋值操作叫做定义)
*
* - > 基本数据类型值(值类型),是按照值来操作的:把原有的值复制一份放到新的空间或位置上,和原来的值没有关系
*
* = > 引用数据类型的值不能直接存储到当前的作用域下(因为可能存储的内容过去复杂),需要先开辟一个新的空间(理解为仓库),把内容存储到这个空间中。
* var obj = {n: 100};
* 1) 首先开辟一个新的内存空间(堆内存空间),把对象中的键值对依次存储(为了保证后面查找该空间,此空间有一个 16 进制的地址)
* 2)声明一个变量
* 3)让变量和空间地址关联一起(把空间地址赋值给变量)
*
* - > 引用类型不是按照值来操作,它操作的是空间的引用地址:把原来空间的地址赋值给新的变量,但是原来的空间没有被克隆,还是一个空间,这样就会出现多个变量关联的是相同的空间,相互之间存在影响。
*
* 栈内存 和 堆内存
*
* 栈内存:提供一个代码运行的环境 本身就是代码运行的环境,所有的基本类型值都会在栈内存中开辟一个对应的位置进行存储。
*
* 堆内存:独立,用来存储引用类型中的信息值(对象存储的是键值对,函数存储的是代码字符串)
*
*/
[ 堆栈练习 ]
var obj = {
n: 10,
m: obj.n * 10
// property 'n' of undefined 报错
}
console.log(obj.m);
/**
* 1. 形成一个全局作用域
* 2. 代码自上而下执行
* 1.首先开辟一个堆内存,把键值对存储到堆内存中,
* n: 10,
m: obj.n * 10 = > obj.n 此时堆内存还没有存储完成,空间地址还没有给 obj ,此时的 obj 是 undefined,
obj.n <=> undefined.n
undefined 是基本数据类型 没有属性,故报错 Uncaught TypeError: Cannot read property 'n' of undefined
at 2.js:15
*
*/
var ary1 = [3,4];
var ary2 = ary1;
ary2[0] = 1;
ary2 = [4,5];
ary2[1] = 2;
arr[1] = 0;
console.log(ary1,ar2); // => 1,0 4,2
JS 中的操作语句
判断语句
- if / else if / else
- if / else if / else