目录复制
JavaScript基础
简介
JavaScript(Java脚本)是一种基于对象(Object)和事件驱动( Event Driven)并具有安
全性能的脚本语言,使用JavaScript可以轻松的实现与HTML的互操作,并且完成丰富的页面
交互效果,它是通过嵌入或调入在标准的HTML语言中实现的,它的出现弥补了HTML的缺陷,
是java与HTML折衷的选择。
其本质:是脚本语言,编程语言,和JAVA语言没有任何联系,体系非常灵活
其语法结构:单线程,异步,解释性语言,弱类型
js引入方式
javascript有三种引入方式:
1、行内引入:
<开始标签 on+事件类型=“js代码”></结束标签>
行内引入方式必须结合事件来使用,但是内部js和外部js可以不结合事件
// JS常用事件(使用时在最前面加上on)
// blur 失去焦点
// change 下拉列表选项中项改变或文本框内容改变
// click 鼠标点击
// dbclick 鼠标双击
// focus 获得焦点
// keydown键盘按下
// keyup 键盘弹起
// load 页面加载完毕
// mousedown 鼠标按下
// mouseover 鼠标经过
// mousemove鼠标移动
// mouseout 鼠标离开
// mouseup 鼠标弹起
// reset 表单重置
// select 文本被选择
// submit 表单提交
2、内部引入:
在head或body中,定义script标签,然后在script标签里面写js代码
<script>
Js代码
</script>
3、外部引入:
定义外部js文件(.js结尾的文件)
<script type="text/javascript" src="demo.js"></script>
JS语法
变量
命名变量
- 变量是内存中运行的最小单位
- js里边:字母、数字、下划线、$符号、汉字 等5个组成部分,数字不能作为名字的
开始内容。
var shoudu = “xxxx”;
var abc_$_123 = “hello”;
var 首都 = “北京”;//可以使用但是不建议使用中文
var 99_num = 101; //错误变量名字
声明变量
JS中声明变量有三种方式:var,let,const
var(最常用)
存在变量提升,可以多次声明,可以多次赋值,无自身作用域
let
无变量提升,不可以多次声明,可多次赋值,有自身作用域
let一般用于循环遍历计数
const
无变量提升,不可以多次声明,不可多次赋值且定义一定要赋值,有自身作用域
const一般用于写在全局作用域作常量
运算符
算术运算符
+ - * / %取余数(模) ++ --
i++ : 先赋值、再++计算
++i : 先++计算,再赋值
> < >= <= != ==
===全等于,全等于===:比较值的类型和数据大小 ,等于==: 比较值的数据大小
!==不全等于
返回布尔数据类型
console.log(10=="10"); //true
console.log(10==="10"); //false
console.log(10===10); //true
逻辑运算符
1 && 逻辑与
两边结果都为真,结果为真
2 || 逻辑或
两边结果只要有一个为真,结果为真
3 !逻辑取非
真即假,假即真
数据类型
各种数据之间的运算
javascript(9种):
number(int/float) string boolean null undefined object(对象) symbol(标识符) Array(数组) function
undefined未定义类型:使用一个没有声明但没赋值的变量。
十进制: var age = 23;
八进制: var score = 023;
十六进制:var color = 0x25;
弱类型
按照计算机语言的类型系统的设计方式,可以分为强类型和弱类型两种。二者之间的
区别,就在于计算时是否可以不同类型之间对使用者透明地隐式转换。从使用者的角度来
看,如果一个语言可以隐式转换它的所有类型,那么它的变量、表达式等在参与运算时,
即使类型不正确,也能通过隐式转换来得到正确地类型,这对使用者而言,就好像所有类
型都能进行所有运算一样,所以这样的语言被称作弱类型。
比如在C语言
(1)若运算数中有double型或float型,则其他类型数据均转换成double类型进行运算。
(2)若运算数中最长的类型为long型.则其他类型数均转换成long型数。
(3)若运算数中最长类型为int型,则char型也转换成int型进行运算。算术转换是在运算过程中自动完成的。
(
由于JS的弱类型特性,在JS中数据转换就比较不同了
举个例子
var a=100,var b="1" var c=a+b ?//c="1001"
其他数据类型一般不参与运算或者比较,重点讲解String和Number的特性
Number
1.Number类型与String类型运算:
除了加号(+)是连接运算,其余为数值与数值之间的运算
console.log(5-"0"); // 5
console.log(5+"0"); // 连接操作 50
console.log(5*"0"); // 0
console.log(5/"0"); // 5/0 数值运算为 infinity(无穷大)
2.Number类型和Boolean类型运算:
将Boolean类型数据转换为Number类型进行数值运算
console.log(5+true); //6
console.log(5-false); //5
console.log(5*false); //0
console.log(5/false); //infinity
3.Number类型和undefined类型运算:
输出的都是NaN(不是数字)
4.Number类型与Null类型运算:
Null类型数据转换为0,进行数值运算
console.log(5+null); //5
console.log(5-null); //5
console.log(5*null); //0
console.log(5/null); //infinty
1.Number类型与String类型比较运算:
字符串为纯数字串,转换为Number类型进行比较,字符串中包含字母,输出结果都为false.
console.log(5>"4"); //true
console.log(5>"4ab"); //false
2.Number类型与Boolean类型比较运算:
Boolean类型数据先转换为Number类型再进行比较
console.log(5>true); //true
console.log(5<false); //false
3.Number类型与undefined类型比较运算:
输出的结果都是false
console.log(5>undefined); //false
console.log(5<undefined); //false
4.Number类型与Null类型比较运算:
null类型先转换为Number类型再进行比较
console.log(5>null); //true
console.log(5<null); //false
String
1.String类型与Boolean类型数据运算:
若字符串中有非数字字符串, 加号(+)为连接操作.其余输出结果为NaN
若字符串中是纯数字字符串, 加号(+)为连接操作,其余为数值运算
console.log("5"+true); //5true
console.log("5"-true); //4
console.log("5"*true); //5
console.log("5"/false); //infinity
console.log("5a"+true); //5atrue
console.log("5a"-true); //NaN
console.log("5a"*true); //NaN
console.log("5a"/true); //NaN
2.String类型与undefined类型数据运算:
无论字符串是纯数字串还是含有字符的字符串,都遵循与加号 (+) 运算
实现的是连接操作,其余的运算输出的是NaN
console.log("5"+undefined); //5undefined
console.log("5"-undefined); //NaN
console.log("5"*undefined); //NaN
console.log("5"/undefined); //NaN
console.log("5a"+undefined); //5aundefined
console.log("5a"-undefined); //NaN
console.log("5a"*undefined); //NaN
console.log("5a"/undefined); //NaN
3.String类型与Null类型数据运算:
若字符串中有非数字字符串, 加号(+)为连接操作.其余输出结果为NaN
若字符串中是纯数字字符串, 加号(+)为连接操作,其余为数值运算
console.log("5"+null); //5null
console.log("5"-null); //5
console.log("5"*null); //0
console.log("5"/null); //infinity
console.log("5a"+null); //5anull
console.log("5a"-null); //NaN
console.log("5a"*null); //NaN
console.log("5a"/null); //NaN
1.String类型与Boolean类型比较运算:
若字符串中有非数字字符串, 输出结果都是false
若字符串中是纯数字字符串, 转换为数值后进行比较
console.log("5">true); //true
console.log("5a">true); //false
2.String类型与undefined类型比较运算:
输出结果都是false
console.log("5">undefined); //false
console.log("5"<undefined); //false
console.log("5a">undefined); //false
3.String类型与null类型比较运算
若字符串中有非数字字符串, 输出结果都是false
若字符串中是纯数字字符串, 转换为数值后进行比较
console.log("5">null); //true
console.log("5a">null); //false
数组
//修改原有数组
push()在末尾添加元素
pop()删除最后一个元素,返回该元素的值
shift()删除第一个元素,返回该元素的值
unshift()在数组头部添加元素,返回该数组长度
sort(),对数组的元素进行排序。
reverse(),将数组中元素的位置颠倒,并返回该数组。数组的第一个元素会变成
最后一个,数组的最后一个元素变成第一个。该方法修改原数组。
splice(start,deleteCount?,item1?) ,通过删除或替换现有元素或者原地
添加新的元素来修改数组,并以数组形式返回被修改的内容(如果只删除了一个
元素,则返回只包含一个元素的数组。如果没有删除元素,则返回空数组)。
//不改变原有数组
slice(begin?,end?),返回一个新的数组对象,这一对象是一个由 begin 和
end 决定的原数组的浅拷贝(包括 begin,不包括end)。
concat(),于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
join(),将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个
字符串。如果数组只有一个项目,那么将返回该项目而不使用分隔符(默认使用’,'
分隔,如果使用"",则所有元素之间都没有任何字符)。
字符串
charAt() 方法可返回字符串中指定位置的字符。
concat() 方法用于连接两个或多个字符串。
indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。没找到返回-1
includes() 方法用于判断字符串是否包含指定的子字符串。
match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。返回数组
repeat() 方法字符串复制指定次数。
replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹
配的子串,replaceAll()替换所有
search() 方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符
串。返回与指定查找的字符串或者正则表达式相匹配的 String 对象起始位置。
slice(start, end) 方法可提取字符串的某个部分,并以新的字符串返回被提取的部分。
substring() 方法用于提取字符串中介于两个指定下标之间的字符。
split() 方法用于把一个字符串分割成字符串数组。
trim() 方法用于删除字符串的头尾空白符,空白符包括:空格、制表符 tab、
换行符等其他空白符等。
对象
对象简介
对象是引用数据类型,是保存复杂数据类型的容器,它是多个属性(数据)和方法(功能)的集合
它允许动态的添加和删除属性,一共分为3种类型的对象
1.内建对象
由ES标准中定义的对象,在任何的ES的实现中都可以使用
比如:math string number boolean object...
2.宿主对象
由js的运行环境提供的对象,目前来讲主要由浏览器提供的对象
比如BOM DOM
3.自定义对象
由开发人员自己创建的对象
定义对象
对于对象的定义可以分为两种方法
1.使用对象字面量,可以在创建对象时,直接指定对象中的属性
语法:{属性名:属性值,属性名:属性值...}
对象字面量的属性名可以加引号,也可以不加,建议不加
如果要使用一些特殊的名字,则必须加引号
以'{ }'作为边界,属性与属性之间用','分开,属性和属性值之间使用':'隔开
2.构造函数创建对象
使用new关键字调用的函数,是构造函数constructor
构造函数是专门用来创建对象的函数
使用typeof检查一个对象时,会返回object
操作对象
- 访问属性:使用点访问符 .
- 给对象添加属性:对象.属性=属性值;
- 删除对象属性:delete 对象.属性;
- 对象属性检测:“属性名” in 对象,有返回true
- object根构造函数:所有的对象都直接或者间接继承Object,都能调用Object原型里面的方法
引用传递和值传递
基本数据类型使用值传递:基本数据类型将值直接保存到内存的栈区中
- js中的变量都是保存在栈内存中的
- 基本数据类型的值是直接在栈内存中存储
- 值与值之间是独立存在的,修改一个变量不会影响其他的变量
对象序列化
1)常规转换
obj.tostring()//默认toString返回 '[object type]' 其中type是对象
的类型,type的值可以是Object,可以重写
2)转化为json字符串
JSON.stringify(obj)
3)查询字符串
var qs= require('querystring'); //引入node.js模块
qs.stringify(obj) =>name=tom&age=12
增强for循环
作用:遍历对象
语法:
for(var 变量 in 对象){undefined}
for...in语句 对象中有几个属性,循环体就会执行几次
每次执行时,会将对象中的一个属性名赋值给变量
函数
使用函数(声明调用,this指向)
函数声明
function 函数名(形参列表){
//函数体
}
var 函数名 = function(形参列表){
//函数体
}
函数调用:两种方式调用
- 调用方式一:名字(); 函数可以多次调用
- 调用方式二:在事件中调用,直接写函数名,不使用括号
函数表达式
- 函数表达式:就是把函数存到变量里。
- 匿名函数:没有名字的函数;
匿名函数在使用时只有两种情况:
- 匿名函数自执行:声明后不需要调用就直接执行(自调用函数),==程序一进入就执行该函数=
(function (形参) {
console.log("立刻执行")
}(回调参数))
- 函数表达式:把函数存到变量,或将函数存到数组的对应位置里等,调用时通过变量或
数组对应位置进行调用。
调用时需要写括号。
函数传参
形参:形式上的参数——给函数声明一个参数;
实参:实际的参数——在函数调用时给形参赋的值
函数内部属性
函数内部属性只能在函数内部才能访问
arguments
arguments是一个类数组对象,包含着传入函数中的所有参数。arguments主要用途是保存
函数参数。
// 当传递的实参个数超过形参的个数的时候不会报错,所有的实参都会保存在arguments里
callee属性
arguments 对象有一个名为callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数。
arguments.callee 实际上就是函数名。
length 属性
arguments 对象的 length 属性返回实参个数。
this指向问题
this:执行环境上下文对象,它指向谁取决于什么时候调用、被谁调用。
- 在方法中,this 表示该方法所属的对象。
- 如果单独使用,this 表示全局对象。
- 在函数中,this 表示全局对象。
- 在事件中,this 表示接收事件的元素。
- 在显式函数绑定时,我们可以自己决定this的指向
补充: 预编译
在方法中this 表示该方法所属的对象。
var person = {
name:'叶子yes',
sayName: function () {
console.log(this.name);
}
}
//person对象调用了该方法,因此this指向person
person.sayName() // '叶子yes'
单独使用this 表示全局对象。
var name = 'hello'
var person = {
name: '叶子yes',
sayName: function () {
console.log(this.name);
}
}
var a = person.sayName
//这里是全局对象调用了sayName方法,因此this指向全局对象window,结果为'hello'
//注意:在node环境下执行时,结果为undefined
a()
在函数中this 表示全局对象。
在浏览器中,指向的是window
在node中,指向的就是global对象
在事件中this 表示接收事件的元素。
<button onclick="this.style.display='none'"> 点我后我就消失了 </button>
//this指向button
在 JavaScript 中函数也是对象,对象则有方法,apply 和 call 就是函数对象的方法。
这两个方法异常强大,他们允许切换函数执行的上下文环境(context),即 this 绑定的对
象。(一般不用)
在下面例子中,当我们使用 person2 作为参数来调用 person1.sayName 方法时, this 将指
向 person2, 即便它是 person1 的方法:
var person1 = {
name: 'zhangsan',
sayName: function () {
console.log(this.name);
}
}
var person2 = {
name:'叶子yes'
}
//this指向person2
person1.sayName.call(person2) //叶子yes
异步(最重点)
同步任务(synchronous)和异步任务(asynchronous)。
同步任务是那些没有被引擎挂起、在主线程上排队执行的任务。只有前一个任务执行完毕,才能执行后一个任务。
异步任务是那些被引擎放在一边,不进入主线程、而进入任务队列的任务。只有引擎认为某个异步任务可以执行了(比如 Ajax 操作从服务器得到了结果),该任务(采用回调函数的形式)才会进入主线程执行。排在异步任务后面的代码,不用等待异步任务结束会马上运行,也就是说,异步任务不具有“堵塞”效应。
异步操作模式
1.回调函数
function f1(callback) {
// ...
callback();
}
function f2() {
// ...
}
f1(f2);
f2写成f1的回调函数。
f2必须等到f1执行完成,才能执行。
回调函数的优点是简单、容易理解和实现,缺点是不利于代码的阅读和维护,各个部分之
间高度耦合(coupling),使得程序结构混乱、流程难以追踪(尤其是多个回调函数嵌套
的情况),而且每个任务只能指定一个回调函数
介绍两个定时器setInterval(隔一段时间执行)和setTimeout(执行一次)
setInterval(function(){
执行代码
},时间间隔(毫秒))
setTimeout(function(){
执行代码
},时间间隔(毫秒))
clearTimeout(定时器标识)//清除setTimeout定时器
clearInterval(定时器标识)//清除setInterval定时器
2.事件监听
对于元素事件的监听也是异步的,因为只有满足==事件触发条件==时才会执行相应的函数
异步练习
下面是本节课最难也是最全面的一道题,包含变量作用域,定时器,异步,回传参数
function fn1() {
for (var i = 0; i < 4; i++) {
var tc = setTimeout(function (i) {
console.log(i);
clearTimeout(tc);
},10, i)
//i为回传参数
}
}
fn1();//输出结果0,1,2
提前看了博客的同学可以思考为什么结果是这个,如果我们要输出原本以为的
0,1,2,3的结果该如何修改?