JavaScript
JS是一种轻量级的变成语言
JS是可插入HTML页面的编程代码
JS插入HTML页面后可由所有的现代浏览器执行
JavaScript主要分为三个部分:
1、ES语法核心部分,控制语句、函数、对象…
ES是一种浏览器标准,目前最受欢迎的是ES6,目前最新的是ES10.
2、BOM浏览器对象模型,主要用于客户端浏览器的管理
3、DOM文档对象模型,可以利用这个增删改查网页中的元素
jQuery是JavaScript的一个函数库,即API库
VUE是JavaScript的一个框架
作用:
- 直接写入HTML输出流, 只能在 HTML 输出中使用 document.write。如果您在文档加载后使用该方法,会覆盖整个文档。
- 对事件的反应
- 改变HTML内容,document.getElementById(“some id”) DOM中查找元素
- 改变HTML图像
- 改变HTML样式
ES
用法
在标签中,对于JS 一般放在两个地方,一个是head中,另一个是文档底部。这样不会影响文档的结构
一般最好放在文档的底部,放在头部的JS,可能在页面尚未加载完成时被调用
外部的JS
<script src="URL"></script>
语法
语句
语句向浏览器发出的命令,语句的作用是告诉浏览器该做什么
末尾用 ‘’ ; ‘’ 分隔
浏览器按照编写顺序依次执行每条语句
在代码块的作用是一并地执行语句序列,就是在块中逐条执行
//向指定ID的HTML元素输出指定文本
document.getElementById("ID值").innerHTML="输出语句";
标识符
定义类
语句 | 描述 |
---|---|
const | 定义的变量不可修改,而且必须初始化,即要给值。 |
var | 定义的全局变量,可以修改,不初始化会输出undefined。 |
let | 局部变量,是块级作用域,函数内部使用let定义后,对函数外部无影响 |
funcation | 定义一个函数 |
return | 退出函数 |
条件
语句 | 描述 |
---|---|
if…else | 用于基于不同的条件来执行不同的动作 |
switch | 基于不同的条件来执行不同的动作 |
//if可以判断范围,但是在运行效率上要低于switch
if(条件){代码块}else{代码块}
//switch:只能选等值的条件
switch(n)
{
case 1:{代码块1}break;
case 2:{代码块2}break;
default:{默认代码块}
}
循环
语句 | 描述 |
---|---|
do…while | 执行一个语句块,在条件语句为true |
while | 当条件语句为true时,执行语句块 |
for | 在条件语句为true时,可以将代码块执行指定次数 |
for…in | 用于遍历数组或者对象的属性(对数组或对象的属性进行循环操作) |
continue | 跳过本地迭代, |
break | 跳出当前循环,只能跳一层 |
异常
语句 | 描述 |
---|---|
throw | 抛出异常 |
try…catch | 处理异常 |
折行
所谓的折行就时将一行代码分成两行写,让逻辑更加清晰
//可以在文本字符串中使用反斜杠对代码进行换行
document.write("你好\
世界,我是诚哥快打钱。");
//但是不能在代码中折行
document.write \
("你好世界!");
//因为代码一般是可以直接回车换行
字面量
在编程语言中,一般将固定值称为字面量
数字字面两可以是整数或者小数,或者科学计数
字符串字面量:可以使用单引号或双引号 “ffff”
表达式字面量:用于计算 5+6
数组字面量:[1,2,5,3]
对象字面量:定义一个对象;{常量名:“常量值”,…}
函数字面量:定义一个函数。 function 函数名(a,b){return a*b;}
注释
与Java一样
数据类型
值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、唯一值(Symbol)
引用数据类型:对象(Object)、数组(Array)、函数(Function)
PS
- Symbol 是ES6引入的一种新的原始数据类型,表示独一无二的值.
是为了解决ES5中对象属性名都是字符串容易造成属性名冲突,为避免这种情况个引入的一种新的原始数据
- JS中变量的数据类型是动态的,值是什么类型,变量就是什么类型
- Undefined 表示这个值不含有值,连Null都没有,即没有初始化
- 可以通过将变量的值设置为null来清空变量
- 变量均为对象。当您声明一个变量时,就创建了一个新的对象
- 若将值赋给未声明的变量,该变量将被自动作为window的一个属性
- 非严格模式下给未声明变量赋值创建的全局变量,是全局对象的可配置属性,可以删除。
//指定对象类型时,数据类型不可变?
var carname=new String;
var x= new Number;
var y= new Boolean;
var cars= new Array;
var person= new Object;
变量
//变量有三种定义方式
let 局部变量,值可以改变
var 全局变量
const 虚假常量 不能重新赋值 可以修改属性 全局
// 创建常量对象
const car = {type:"Fiat", model:"500", color:"white"};
// 修改属性:
car.color = "red";
// 添加属性
car.owner = "Johnson";
变量提升
所谓变量提升就是变量声明总是会被解释器悄悄的提升到方法体的最顶部,函数也是一个变量。
及在写JS代码时变量,可以先使用然后再声明
变量的生命周期:
变量的声明期从它们被声明的事件开始
局部变量会在函数运行以后被删除
全局变量会在页面关闭后删除
变量的类型操作
typeo 操作符
用来检测变量的数据类型,基本类型返回基本类型,引用类型统一返回Object
typeof 变量/字面量
null
主动释放一个变量引用的对象,表示一个变量不再指向任何对象地址
当使用完一个比较大的对象时,需要对其进行释放内存时,可以设置为null来清空对象。
注意 null 只是没有值,它数据类型为Object
var person =null; //值为 null ,但类型为对象
undefined
是所有没有赋值变量的默认值,自动赋值。
任何变量都可以通过设置值为undefined来清空。类型为undefined
var person; //值为 undefined(空,没有),类型是undefued(没有)
undefined与null的异同
共同点
都是原始类型,保存再栈中变量本地
不同点
值相等,但类型不同
undefined 表示变量声明过但并未赋过值
var a; //a自动被赋值为 undefined
null 表示一个变量将来可能指向一个对象
var emps=['ss','nn'];
emps = null; //释放指向数组的引用
使用
使用规范
运算符前后需要添加空格
通常用4个空格符号来缩进代码块,不推荐用tab来缩进,不同编辑器tab解析不一样
每行代码字符小于80,若超过80建议在运算符或者逗号后换行
载入外部JS时使用简洁的格式载入JS文件(Type属性不是必须的)
使用小写文件名,大多服务器都是大小写敏感的,为保持统一的风格,就统一使用小写文件名
一条语句通常以分号作为结束符
当语句复杂时,将做花括号放在第一行的结尾,左花括号前添加一空格,将右花括号独立放在一行,不要以分号结束一个复杂的声明
对象定义的规则:
将左花括号与类名放在同一行
冒号与属性值间有个空格
字符串使用双引号,数字不用
最后一个属性值后面不要加逗号
将右花括号独立放在一行,并以分号作为结束符号
短的对象代码可以直接写成一行
命名规则
一般代码语言命名规则都是
变量名和函数为小驼峰法标识,即除第一个单词之外,其他单词首字母大写
全局变量与常量为大写
HTML和CSS的横杠(-)字符:可以用来连接属性名 (data-某某某),JS中不行
下划线 SQL中比较喜欢用下划线来分隔单词
帕斯卡拼写法:将函数的首字母或几个字母提取出来组成一个唯一标识
驼峰法:第一个单词首字母小写,其余单词首字母大写
输出
window.alert() : 弹出警告框
document.write() :将内容写到HTML文档中
inner HTML 写入到HTML元素
console.log:写入到浏览器的控制台
字符串
字符串属性
原始值字符串,如"John",没有属性和方法(因为他们不是对象)
原始值可使用 JS 的属性和方法,因为 JS 在执行方法和属性时可以吧原始值当作对象。
属性 | 描述 |
---|---|
constructor | 返回创建字符串属性的函数 |
length | 返回字符串的长度 |
prototype | 允许你向对象添加属性和方法 |
字符串方法
查询方法
方法 | 描述 |
---|---|
charAt() | 根据索引找字符,返回指定索引位置的字符 |
charCodeAt() | 返回指定索引位置字符的Unicode值 |
concat() | 连接两个或多个字符串,返回连接后的字符串 |
fromCharCode() | 将Unicode转换为字符串 |
indexOf() | 根据字符找索引,返回字符在串中第一次出现的索引 |
lastIndexOf() | 返回字符在串中最后一次出现的索引 |
match() | 找到一个或多个正则表达式的匹配 |
replace() | 替换与正则表达式匹配的子串 |
search() | 检索与正则表达式相匹配的值 |
功能方法
方法 | 描述 |
---|---|
slice() | 提取字符串的片段,并在新的字符串中返回被提取的部分 |
split() | 把字符串分割为子字符串数组 |
substr(a,b) | 从索引a开始提取b个字符 |
substring(a,b) | 提取索引a,b之间的字符 |
toLocaleLowerCase() | 根据主机语言环境将字符串转为小写,只有几种语言具有地方特有的大小写映射 |
toLocaleUpperCase() | 根据环境转大写,其余同上 |
toLowerCase() | 把字符串转换为小写,主要就是用这个东西 |
toUpperCase() | 把字符串转换为大写 |
toString() | 返回字符串对象值 |
trim() | 移除字符串首尾空白 |
valueOf() | 返回 某个串对象的原始值 |
运算符
逻辑运算
出现=是因为JS变量的数据类型是变换的, 只比较两个量的值
运算符 | 描述 |
---|---|
== | 值相等,8==“8” 为 true |
=== | 绝对等于(值和类型均相等) |
!= | 值不等于 |
!== | 绝对不等于(值和类型均不等于) |
调试
console.log()// 将值打印到控制台
设置断点
var x=15*5;
debugger; //代码将会在第三行前停止执行
document.getElementbyId("demo").innerHtml =x;
严格模式(use strict)
严格模式即在严格条件下运行
严格模式通过在脚本或函数的头部添加,也只允许出现在脚本或函数的开头。
<script>
"use strict";
x = 3.14; // 报错 (x 未定义)
</script>
<script>
"use strict";
myFunction();
function myFunction() {
y = 3.14; // 报错 (y 未定义)
}
</script>
在函数内部声明是局部作用域(只在函数内部使用严格模式)
<script>
x = 3.14; // 不报错
myFunction();
function myFunction() {
"use strict";
y = 3.14; // 报错 (y 未定义)
}
</script>
严格模式的限制
1、不允许使用未声明的变量,变量提升依旧能用
x = 3.14; // 报错 (x 未定义)
2、不允许删除变量,函数、对象也都是变量
var x = 3.14;
delete x; //报错
3、不允许变量重名
function x(p1, p1) {}; // 报错
4、不允许使用八进制
var x = 010; // 报错
5、不允许使用转义字符
var x = \010; // 报错
6、不允许对只读属性赋值
Object.defineProperty(obj, "x", {value:0, writable:false});
obj.x = 3.14; // 报错
7、不允许对一个使用getter方法读取的属性进行赋值,即get方法
var obj = {get x() {return 0} };
obj.x = 3.14;
8、不允许删除一个不允许删除的属性
delete Object.prototype; // 报错
9、变量名不能使用"eval"字符串
var eval = 3.14; // 报错
10、不能使用"arguments"字符串
var arguments = 3.14; // 报错
11、不能使用一面这种语句
with (Math){x = cos(2)}; // 报错
12、由于一些安全原因,在作用与eval()创建的创建的变量不能被调用
eval ("var x = 2");
alert (x); // 报错
13、禁止this关键字指向全局对象
function f(){
return !this;
}
// 返回false,因为"this"指向全局对象,"!this"就是false
function f(){
"use strict";
return !this;
}
// 返回true,因为严格模式下,this的值为undefined,所以"!this"为true。
//因此,使用构造函数时,如果忘了加new,this不再指向全局对象,而是报错。
14、保留关键字,使用保留关键字将报错
关键字 |
---|
implement |
interface |
let |
package |
private |
protected |
public |
static |
yield |
var public = 1500; // 报错
表单
表单验证
可以验证表单字段值是否存在,如果不存在就弹出信息来阻止表单提交
<form name="myForm" action="demo_form.php" onsubmit="return validateForm()" method="post">
名字: <input type="text" name="fname">
<input type="submit" value="提交">
</form>
function validateForm() {
var x = document.forms["myForm"]["fname"].value;
if (x == null || x == "") {
alert("需要输入名字。");
return false;
}
}
this关键字
面向对象语言中表示当前对象的一个引用
但在 JS 中 this 不是固定不变的,它会随着执行环境的改变而改变
在方法中 this表示该方法所属的对象
方法名 : function() {
return this.属性1 + " " + this.属性2;
}
单独使用 表示全局(Global)对象,在严格模式中这样使用会报错
var x = this;
在函数中 表示全局对象
在浏览器中,window就是该全局对象,为[object Window]
严格模式下未undefined
//默认
function 函数名() {
return this;
}
//严格
"use strict";
function 函数名(){
return this;
}
在事件中 this 表示接受事件的元素
<button οnclick="this.style.display='none'">
点我后我就消失了
</button>
显式函数绑定
在 JS 中函数也是对象,对象则有方法,apply和call就是函数对象的方法
这两个方法异常强大,他们允许切换函数执行的上下文环境,即this绑定的对象。
apply():调用一个方法,用另一一个对象替换当前对象
call(): 调用一个方法,用另一个对象替换当前对象
两个作用相同,只是能加的参数不同
对象1.apply(对象2,数组);
对象1.call(对象2,arg1,arg2....);
void
javascript:void(0) 该操作符指定要计算一个表达式但是不返回值,即可以进行操作但是没有值
<script type="text/javascript">
void func()
javascript:void func()
</script>
或者
<script type="text/javascript">
void func(
javascript:void func()
)
</script>
这玩意就像一个没有返回值的函数,0是一亦是万,大梦一场终究虚无
<a href="javascript:void(alert('Warning!!!'))">
点他有反应</a>
href="#"与href="javascript:void(0)"的区别
“#” 包含了一个位置信息,默认的锚是#top,就是网页的上端
而javascript:void(0),仅仅表示一个死连接
在页面很长的时候会使用#来定位页面的具体位置,格式为:#+id
如果要定义一个死链就用javascript:void(0)。
<a href="javascript:void(0);">点我没有反应的!</a>
<a href="#pos">点我定位到指定位置!</a>
<br>
...
<br>
<p id="pos">尾部定位点</p>
异步编程
异步相当于多线程,同步相当于串行
异步是与同步相对的概念
同步按代码顺序执行,异步不按代码顺序执行,异步的执行效果更高
通俗来讲就是 从主线程发射一个子线程来完成任务
何时使用
完成一些可能消耗时间足够长以至于被用户察觉的事情时使用
回调函数
子线程发射出去之后,就与主线程失去了同步,无法确定它的结束。
这时就需要用到回调函数
回调函数是一个函数,当异步任务开始时,规定它任务完成时的操作
即用来监听异步的完成,以及在完成后进行一些操作。
AJAX
异步的 JS 和 XML
不是新的编程语言,而是一种使用现有标准的新方法
最大的是优点是在不更新整个页面的情况喜喜啊,可以与服务器交换数据并更新部分网页
不需要任何浏览器插件,但需要用户允许 JS 在浏览器上执行
函数
函数可以通过声明定义也可以是一个表达式
函数声明之后不会立即执行,会在我们需要的时候调用到
函数表达式可以存储在变量中,这个变量的类型就是函数变量,实际上是一个匿名函数,没有函数名
还可以用Function()构造函数,但在很多时候在JS中要避免使用new关键字可以用函数表达式来代替
//函数声明
function 函数名(参数){执行的代码;}
//函数表达式
var/let/const 变量名=function(参数){执行的代码;}
//Function()构造函数
var/let/const 变量名=new 函数名("参数1","参数2",...,"代码块");
函数提升
只能提升声明带函数名的函数,使用表达式定义的函数暂时无法提升
自调用函数
函数表达式可以自调用,自调用表达式会自动调用,
如果表达式后面紧跟着(),则会自动调用
不能自调用声明的函数
通过添加括号,来说明它是一个函数表达式
箭头函数
(函数表达式全部都写成这个)
箭头函数的 表达式 的语法比 普通函数的表达式 更简洁
箭头函数是 函数表达式
//参数只有一个的时候,
const 变量名 = (参数) => 表达式(一条语句);
const 变量名 = (参数) => {代码块};
//若要返回一个对象
const 变量名 = (参数) => ({代码块});
有的箭头函数都没有自己的 this ,不适合定义一个对象方法
当我们使用箭头函数的时候,箭头函数会默认帮我们绑定外层 this 的值,所以在箭头函数中 this 的值和外层 this 的值是一样的
箭头函数是函数表达式,不能提升,使用前要定义
使用 const 比使用 var 更安全,因为函数表达式始终是一个常量
如果函数部分只是一个语句,则可以省略 return 和大括号 {} ,这样是一个好的习惯
**注意:**IE11 及更早 IE 版本不支持箭头函数。
方法与函数的区别
通过对象调用的函数称之为方法,方法本身也是函数,它只是比较特殊的函数。
通过函数名调用的就是函数
都是通过function定义的,不过一个名在前一个名在后
函数
function 函数名(参数)
{ return 结果; }
//调用
myFunction(参数);
//返回值
结果
方法
var obj = {
属性名:属性值,
方法名:function() {方法内容}
}
//调用
obj.method();
//打印结果
返回结果
参数
JS 函数对参数的值没有任何检查
显示参数与隐式参数
显示参数在函数定义时列出来 形参
隐式参数在函数调用时 传递给函数真正的值 实参
参数规则
JS 函数定义显示参数时没有指定数据类型
JS 函数对隐式参数没有进行 类型与个数 的检测
默认参数
ES6 支持带有默认参数,就判断 undefined 和 || 的操作
arguments对象
JS 函数有个内置对象 arguments 对象
arguments 对下给你包含了函数调用的参数数组
通过这种方式可以很方便的找打最大的一个参数值
传递
通过值传递参数
在函数中调用的参数是函数的隐式参数
JS 隐式参数同故宫值来传递,函数仅仅只是获取值
若函数修改参数的值,不会修改显示参数的初始值
隐式参数的改变在函数外是不可见的
通过对象传递参数
在 JS 中,可以引用对象的值
因此我们可以在函数内部修改对象的属性,就会修改其初始的值
修改对象属性作用与函数外部(全局变量)
修改对象属性在函数外是可见的
调用
JS 函数有4中调用方式
每种方式的不同在于 this 的初始化
this
一般而言,在JS中,this指向函数执行时的当前对象
this只是保留关键字,不能修改它的值
作为一个函数调用
函数不属于任何对象,但在JS中它始终是默认的全局对象
在HTML中默认的全局HTML页面本身,所以函数是属于HTML页面
在浏览器中的页面对象是 浏览器窗口对象(window 对象),函数会自动变为window对象的函数
函数名.() 和 window.函数名() 是一样的
function myFunction(a, b) {
return a * b;
}
myFunction(10, 2); // myFunction(10, 2) 返回 20
全局对象
当函数没有被自身的对象调用时 this 的值就会变成全局对象
在 web 浏览器中全局对象是浏览器窗口(window对象)
注意:
函数作为全局对象调用,会使 this 的值成为全局对象
使用 window 对象作为一个变量容易造成程序崩溃
作为一个方法调用
在这里 this 指向 定义该方法的对象
函数作为额对象的方法调用,会使得 this 的值成为对象本身
var 变量名(对象) = {
属性名: "属性值",
方法名: function(参数){代码块}
}
使用构造函数调用函数
若函数调用前使用了 new 关键字,则是调用了构造函数
看起来像是创建了新的函数,但实际上 JS 函数是重新创建对象
构造函数的调用会创建一个新的对象,新的对象会继承构造函数的属性和方法。
构造函数中 this 没有任何值
this 的值在函数调用实例化对象时创建
//构造函数
function 函数1 (参数1,参数2){
this.属性1 = 参数1;
this.属性2 = 参数2
}
//创建一个新对象
var x = new 函数1("参数3","参数4");
x.属性2; //返回 参数4
作为函数方法调用函数
在 JS 中,函数是对象,所以函数有它的属性和方法
call() 和 apply() 就是预定义的函数方法,两个方法可以用于调用函数,两个方法第一个参数必须是对象本身
两个方法的区别:
apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,而call则作为call的参数传入(从第二个参数开始)
在严格模式下,在调用函数时第一个参数会成为 this 的值,即使该参数不是一个对象
在非严格模式下,若第一个参数的值是 null 或 undefined,它将 使用全局对象替换
PS:
通过 call() 或 apply() 方法可以设置 this 的值,且作为已存在对象的新方法调用
作用域与作用域链
作用域
作用域就是一套规则,用于确定在何处以及如何查找变量(标识符)的规则
在 JS 中,作用域分为 全局作用域 和 函数作用域
作用域有上下级关系,上下级关系的确定就看函数是在那个作用域下创建的。
作用域最大的用处就是隔离变量,不同作用域下同名变量名不会有冲突
变量取值:到创建这个变量的 函数的作用域中取值
全局作用域
代码在程序的任何地方都能被访问
window对象的内置属性都拥有全局作用域
函数作用域
在固定代码片段才能被访问
词法作用域
写代码时将变量和块作用域写在哪里来决定,也就是词法作用域是静态的作用域,在你书写代码时就确定了
词法作用域的创建发生在预编译阶段,因为词法阶段属于预编译的一个过程
js中其实只有词法作用域,并没有动态作用域,this的执行机制让作用域表现的像动态作用域,this的绑定是在代码执行的时候确定的。
注1:eval()和with可以通过其特殊性用来“欺骗”词法作用域,不过正常情况下都不建议使用,会产生性能问题。
注2:ES6中有了let、const就有了块级作用域
自由变量
这是一个相对的概念
在A作用域中使用的变量X,却没有在A作用域中声明(即它在其他作用域中声明的),对于A作用域来说,x就是一个自由变量
var x = 10;
var y = () => x+1;//x对于y而言就是一个自由变量
作用域链
一般情况下,变量取值是从创建这个变量的函数作用域中取值
但是若在当前作用域中没有找到值,就会向上级作用域去查,直到查到全局作用域,这个查找过程形成的链条称之为作用域链。
这是一个老千层饼了,只能上下查,不能左右查。
闭包
前言
在 JS 中闭包无处不在,没看到只是你瞎了,白长了一双水汪汪的大眼睛。
闭包是基于词法作用域书写代码时产生的自然结果,不需要有意识的创建闭包。
闭包
当函数 可以记住 并访问所在的词法租用域时,就产生了闭包(你不知道的 JS )
闭包是指有权访问另一个函数作用域中的变量的函数( JS 高级程序设计)
内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数返回(寿命终结)了之后
闭包函数
声明在一个函数中的函数,叫做闭包函数
特点
- 让外部访问函数内部的变量成为可能
- 局部变量会常驻在内存中
- 可以避免使用全局变量,防止全局变量污染
- 会造成内存泄漏(有一块内存空间被长期占用,而不被释放)
闭包的创建
闭包就是可以创建一个独立环境,每个闭包里面的环境都是独立的,互补干扰。
闭包会发生内存泄漏,每次外部函数执行的时候,外部函数的引用地址不同,都会重新创建一个新的地址。
但凡是当前活动对象中有被内部子集引用的数据,那么这个时候,这个数据不会删除,保留一根指针给内部活动对象。
闭包内存泄漏为 :key = value ,key 被删除了 value 常驻内存中;
局部变量闭包升级版(中间引用的变量) => 自由变量
总结:
闭包找到的是同一地址中父级函数中对应变量最终的值,
即在祖传手艺中找最新的对应手艺
JSON
是一种轻量级的数据交换格式
JSON是一种无法注释的独立语言,因为里面的东西都要被转换成字符串,都是值,所以无法注释
JSON易于理解
语法规则
数据为键值对
数据由逗号分隔
大括号保存对象
方括号保存数组
相关函数
函数 | 描述 |
---|---|
JSON.parse(参数) | 将JSON字符串转换为JS对象 |
JSON.stringify(参数) | 将JS值转换为JSON对象 |