这里写自定义目录标题
js基础
一. JavaScript概述
1.1 JavaScript应用场景
网页特效
- 页面的各种动画效果
- 页面的点击/移入事件响应
- 对客户端数据进行验证
服务端开发
Node.js 是运行在服务端的 JavaScript
通过Node.js可以进行服务端开发,步骤如下:
- 导入http模块
- 创建http服务器对象
- 给服务器对象注册(绑定)request事件
- 开启端口监听
通过Node.js开发命令行工具
桌面应用程序
桌面应用程序,又称为 GUI 程序(Graphical User Interface),但是和 GUI 程序也有一些区别。桌面应用程序 将 GUI 程序从GUI 具体为“桌面”,使冷冰冰的像块木头一样的电脑概念更具有 人性化,更生动和富有活力。
Electron 基于 Chromium 和 Node.js,让你使用 JavaScript,HTML 和 CSS 构建跨平台的桌面应用程序
Electron官网:https://www.electronjs.org/
App开发
app在手机中的意思就是application的简称,也就是应用的意思
Cordova提供了一组设备相关的API,通过这组API,移动应用能够以JavaScript访问原生的设备功能,如摄像头、麦克风等。
Cordova还提供了一组统一的JavaScript类库,以及为这些类库所用的设备相关的原生后台代码。
Cordova支持如下移动操作系统:iOS, Android,ubuntu phone os, Blackberry, Windows Phone, PalmWebOS, Bada 和 Symbian。
Cordova官网:https://www.apicloud.com/blogDetails/8078
控制硬件-物联网
物联网(Internet of Things,简称IoT)是指通过各种信息传感器、射频识别技术、全球定位系统、红外
感应器、激光扫描器等各种装置与技术,实时采集任何需要监控、 连接、互动的物体或过程,采集其声、光、热、电、力学、化学、生物、位置等各种需要的信息,通过各类可能的网络接入,实现物与物、物与人的泛在连接,实现对物品和过程的智能化感知、识别和管理。物联网是一个基于互联网、传统电信网等的信息承载体,它让所有能够被独立寻址的普通物理对象形成互联互通的网络 。
Ruff 一个专为硬件开发而设计的JavaScript 运行时,开发者可使用 JavaScript 快速开发智能硬件应用。
Ruff 包含了RuffOS,Ruff SDK、Rap Registry等几个方面。
Ruff官网:https://ruff.io/
游戏开发
游戏开发是创建描述游戏设计、开发和发布的视频游戏的过程。游戏的开发部分通常涉及游戏的编程、编码、渲染、工程和测试。 游戏开发一般主要分为两大块,即程序开发与美术设计。
Cocos Creator 是以内容创作为核心,实现了脚本化、组件化和数据驱动的游戏开发工具。 具备了易于上手的内容生产工作流,以及功能强大的开发者工具套件,可用于实现游戏逻辑和高性能游戏效果。
cocos2d-js官网:https://www.cocos.com/
主要用途
-
嵌入动态文本于HTML页面。
-
对浏览器事件做出响应(对于用户的操作给予响应)。
-
读写HTML元素。
-
在数据被提交到服务器之前验证数据(客户端数据校验)。
-
检测访客的浏览器信息。
-
控制cookies,包括创建和修改等。
-
基于Node.js技术进行服务器端编程。
1.2 JavaScript优点
-
所有主流浏览器都支持JavaScript(支持程度广)。
-
目前,全世界大部分网页都使用JavaScript(用户群体广)。
-
它可以让网页呈现各种动态效果,做为一个Web开发师,如果你想提供漂亮的网页、
令用户满意的上网体验,JavaScript是必不可少的工具(特点)。
-
易学性,学习环境无外不在,只要有文本编辑器,就能编写JavaScript程序。
它是基于Java简化设计而来。
1.3 JavaScript组成部分
JavaScript是由ECMAScript、文档对象模型(Document Object Model:DOM)、浏览器对象模型
(Brower Object Model:BOM)三部分构成。
-
ECMAScript,描述了该语言的基础语法和基本对象(包含内置对象),JavaScript的核心,描述了语言的基本语法(变量、运算符、表达式、流程控制语句等)和数据类型(数字、字符串、布尔、array、函数、对象(obj、[]、{}、null)、未定义),ECMAScript是一套标准.
-
文档对象模型(DOM),描述处理网页内容的方法和接口。通过 DOM,可以访问所有的 HTML 元素,连同它们所包含的文本和属性,可以对其中的内容进行修改和删除,同时也可以创建新的元素;DOM(文档对象模型)是 HTML 和 XML 的应用程序接口(API)。DOM 将把整个页面规划成由节点层级构成的文档。HTML 或 XML 页面的每个部分都是一个节点的衍生物。
-
浏览器对象模型(BOM),描述与浏览器进行交互的方法和接口。BOM提供了独立于内容而与浏览器窗口进行交互的对象,例如可以移动,调整浏览器大小的window对象,可以用于导航的location对象与history对象,可以获取浏览器,操作系统与用户屏幕信息的navigator与screen对象。
1.4 JavaScript的引入方式
HTML 中的脚本必须位于 <script>
与 </script>
标签之间。可放置在页面的 <body>
和 <head>
部分中。
行内引入JavaScript
在标签事件属性中填写JavaScript代码或调用函数时,不是事件=函数名,而是事件=函数名+()
<!-- 行内js的使用(一般不推荐使用 除非代码量非常少)
事件名+执行的js逻辑代码
-->
<input type="button" onclick="alert('我是行内的js方法')" value="点我提示信息">
内部引入JavaScript
可以在 HTML 文档中放入不限数量的脚本。
脚本可位于 HTML 的 <body>
或 <head>
部分中,或者同时存在于两个部分中。
通常的是把函数放入 <head>
部分中,或者放在页面底部.这样就可以把它们安置到同一处位置,不会干扰页面的内容。
<head>
<script>
// 定义了一个方法,以便后续在合适时机进行调用
function show() {
alert('我是页面中的js方法')
}
</script>
</head>
<body>
<input type="button" onclick="show()" value="点我提示信息">
</body>
外部引入JavaScript
也可以把脚本保存到外部文件中。外部文件通常包含被多个网页使用的代码。
外部 JavaScript 文件的文件扩展名是 .js。
如需使用外部文件,请在 <script>
标签的 “src” 属性中设置该 .js 文件:
<!-- 使用外部的js方法
外部文件引入的原则:
css优先引用,js通常放在末尾
-->
<script src="js/myjs.js"></script>
注:引用外部js文件的script标签中不可以写JavaScript代码。
1.5 扩展知识点
1.5.1 向文档写入内容
document.write() 的常用操作:
-
输出文字。
-
除了直接输出文字外,它还支持带有HTML标签的输出内容。
<script>
function myfunction() {
document.write("<h1>我是h1的内容</h1>")
}
</script>
注:如果在文档已完成加载后执行 document.write,整个 HTML 页面将被覆盖。
1.5.2 警告框
alert():
-
alert()方法会弹出警告框。
-
可以添加多个alert();他们会按照顺序依次执行。
<script>
window.alert(5 + 6);
</script>
1.5.3 控制台输出
console.log():
-
写入到浏览器的控制台。
-
如果您的浏览器支持调试,你可以使用 console.log() 方法在浏览器中显示 JavaScript 值。
-
浏览器中使用 F12 来启用调试模式, 在调试窗口中点击 “Console” 菜单。
<script>
a = 5;
b = 6;
c = a + b;
console.log(c);
</script>
1.5.4 向标签设置内容
innerHTML:
写入内容到 HTML 元素。
<body>
<h1>我的第一个web界面</h1>
<p id="p1">我的第一个段落</p>
<script>
document.getElementById('p1').innerHTML ="我的第二个段落"
</script>
</body>
1.5.5 鼠标单击事件
click事件的基本用法
click事件是最常用的事件之一,所谓事件可以简单理解为用户的操作。
<button onclick="myfunction()">点我</button>
1.6 avaScript注释及注意事项
单行注释:
快捷键:ctrl + /
// 单行注释内容
// var name = 'hm';
多行注释:
快捷键:shift alt + a
/* 多行注释内容 */
/*
var age = 18;
var name = 'zs';
console.log(name, age);
*/
文档注释
/** 文档注释内容 */
注意事项:
- 字母的大小写,Name和name是两个不同的标识符。
- 空格和换行。这一点和CSS代码规则类似:多余的空格会被忽略,可以将一行代码分成多行写。
- 分号作为一个语句的结束标志,分号之后是新语句的开始。虽然省略不写通常也是没有问题的,但还是建议大家写上。
二. JavaScript变量和数据类型
2.1 标识符
所谓标识符,就是指变量、函数、属性的名字或者函数的参数(凡是可以自己起名字的地方,都叫标识符)
标识符命名规范(包括函数名,变量等):
-
由字母、数字、下划线、$符号组成;
-
不能以数字开头
-
命名不能是系统的关键字或保留字:比如new ,if,class…;关键字:赋予特殊含义的单词
-
区分大小写
-
命名最好用有意义的名称(见名知意)。比如说name,people…
-
驼峰原则: 首字母小写,多个单词组成,从第二个单词的首字母开始都大写; 比如: getNameById();
-
常量命名: 全部大写,多个单词组成,每个单词之间由下划线分割;APPLICATION_NAME
注:ECMAScript 中的一切,包括变量、函数名和操作符都是严格区分大小写的。
2.2 变量
2.2.1 什么是变量
可以发生改变的量就是变量,变量可以看做是存储数据的容器。
变量是计算机内存中存储数据的标识符,根据变量名称可以获取到内存中存储的数据
使用变量可以方便的获取或者修改内存中的数据。
在我们平时开发中,使用最多的并不是固定的数据,而是会变换的数据。
- 比如购物车商品的数量、价格的计算等等;
- 比如一首歌曲播放的时间、进度条、歌词的展示等等;
- 比如微信聊天中消息条数、时间、语音的长度、头像、名称等等;
- 比如游戏中技能的冷却时间、血量、蓝量、buff时间、金币的数量等等;
2.2.2 变量的命名
-
可以给变量起一个简短名称,这个名称就是变量名。比如 x,或者更有描述性的名称,比如 age、name等。
-
变量名对大小写敏感且必须以字母或下划线开始。可以通过其名称来引用一个变量,以此显示或改变它的值。
2.2.3 变量的声明
-
在 JavaScript 中创建变量通常称为“声明”变量,使用关键字var来声明变量。
-
向变量赋值,使用等号;可以在声明变量时对其赋值,也可以先声明后赋值。
-
可以在一条语句中声明很多变量。该语句以 var 开头,并使用逗号分隔变量即可
声明变量
// 声明一个变量count:
var count;
// 声明一个变量username:
var username;
声明变量并赋值(可以先声明后赋值)
// 变量声明并赋值
var count = 5;
var username= "张三";
// 先声明后赋值
var count ;
count=100;
var username;
username = “张三”;
注:在为变量赋文本值时,请为该值加引号(单引号或双引号都可以)。
如果所赋值的变量还未进行过声明则该变量会自动声明
x = 5; carname = "张三";
// 与下面的效果相同:
var x = 5; var carname = "张三";
再次声明变量,变量也不会丢失其原始值。但是如果再次声明的是不同的值则变量的值会改变
var x = 5;
var x; // 值还是5
var x = 5;
var x = 7; // 值变为7
JavaScript允许一次定义多个变量,还可以在定义变量的同时给变量赋初始值
var a,b,c;
var a=12,b,c=34;
注:如果一个变量没有赋值,它的值是undefined(未定义)。
2.3 关键字 保留字
ECMA-262 描述了一组具有特定用途的关键字。这些关键字可用于表示控制语句的开始或结束,或者用于执行特定操作等。按照规则,关键字也是语言保留的,不能用作标识符。
关键字
break | do | instanceof | typeof |
---|---|---|---|
case | else | new | var |
catch | finally | return | void |
cintinue | for | switch | while |
debugger | function | this | with |
dwfault | if | throw | delete |
in | try |
保留字
ECMA-262 还描述了另外一组不能用作标识符的保留字。尽管保留字在这门语言中还没有任何特定的用
途。但它们有可能在将来被用作关键字。
abstract | enum | int | short |
---|---|---|---|
boolean | export | interface | static |
byte | extends | long | super |
char | final | native | synchronized |
class | float | package | throws |
const | goto | private | transient |
public | implements | protected | volatile |
double | import |
2.4 数据类型
Javascript脚本语言同其他语言一样,有它自身的基本数据类型,表达式和算术运算符及程序的基本程序框架
Javascript提供了五种原始的数据类型和两种特殊数据类型用来处理数据和文字。
变量提供存放信息的地方,表达式则可以完成较复杂的信息处理。
原始数据(基本数据)(简单)类型:
- 数字
- 字符串
- 布尔(Boolean))
- null
- undefine
对象(复杂数据)类型:
1 普通对象
2 特殊对象:
2.1. 全局对象
2.2. 数组
2.3. 函数 【 1.内置函数{1.1全局函数,1.2构造函数} 2.自定义函数】
JavaScript数据类型分为以下几种:
-
字符串(String)
-
数值(Number)
-
布尔(Boolean)
-
数组(Array)
-
对象(Object)
-
空(Null)
-
未定义(Undefined)
-
函数
-
其他
JavaScript 拥有动态类型。这意味着相同的变量可用作不同的类型:
var x; // x 为 undefined
var x = 5; // 现在 x 为数字
var x = "John"; // 现在 x 为字符串
2.4.1 字符串
字符串是存储字符的变量。
字符串可以是引号中的任意文本。可以使用单引号或双引号;
可以使用"+"进行字符串的连接。
注:字符串类型可以和任何类型做+运算;
- 转义符
转义字符 | 表示符号 |
---|---|
’ | 单引号 |
" | 双引号 |
\ | 反斜杠 |
\n | 换行符 |
\r | 回车符 |
\t | 制表符 |
\b | 退格符 |
- 字符串长度
length属性用来获取字符串的长度。
length属性 用来获取数组的长度
var str = 'Hello World';
console.log(str.length);
- 字符串拼接
字符串拼接使用 + 连接。
console.log(11 + 11); //22
console.log('hello' + ' world'); //hello world
console.log('100' + '100'); //100100
console.log('11' + 11); //1111
console.log('male:' + true); //male:true
- 两边只要有一个是字符串,那么+就是字符串拼接功能。
- 两边如果都是数字,那么就是算术功能。
2.4.2 数值
JavaScript 只有一种数值类型。数值可以带小数点。极大或极小的数字可以通过科学计数法来书写
数值可以通过运算符进行计算。
浮点数值的最高精度是16位小数,但是在进行算术计算时其精度远远不如整数。
- 进制
// 十进制
var num = 9;
//进行算数计算时,八进制和十六进制表示的数值最终都将被转换成十进制数值。
// 十六进制
var num = 0xA;
数字序列范围:0~9以及A~F
// 八进制
var num1 = 07; // 对应十进制的7
var num2 = 017; // 对应十进制的15
var num3 = 08; // 对应十进制的8
//数字序列范围:0~7
//如果字面值中的数值超出了范围,那么前导零将被忽略,后面的数值将被当作十进制数值解析
- 浮点数
// 浮点数值的最高精度是 17 位小数,但在进行算术计算时其精确度远远不如整数
var result = 0.1 + 0.2; // 结果不是 0.3,而是:0.30000000000000004
- 数值范围
最小值:Number.MIN_VALUE,这个值为: 5e-324
最大值:Number.MAX_VALUE,这个值为: 1.7976931348623157e+308
无穷大(正无穷):Infinity
无穷小(负无穷):-Infinity
- 数值判断
NaN:not a number
NaN 与任何值都不相等,包括他本身
isNaN: is not a number
2.4.3 布尔(Boolean)
Boolean(布尔)类型用于表示真假:
Boolean 类型仅包含两个值:true 和 false:true表示真 false表示假
使用关系运算符运算的结果,就是布尔数据类型
计算机内部存储:true为1,false为0。
2.4.4 数组(Array)
数组就是将多个元素(通常是同一类型)按一定顺序排列放到一个集合中,这个集合就称之为数组。
数组是一个有序的列表,可以在数组中存放任意的数据,并且数组的长度可以动态的调整。
使用关键字new或 [ ] 创建
创建数组的方式:
-
var 数组名=[数组值…值N];
-
var 数组名= new Array(值1…值N);
-
var 数组名= new Array();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数组</title>
<script>
// 1. 构造函数创建
var persons=new Array()
var persons=new Array(5)
var persons=new Array('孙悟空','唐僧','猪八戒','沙和尚','白龙马')
console.log(persons)
console.log(persons.length)
// 2.快捷创建
var persons=[]
var persons=['孙悟空','唐僧','猪八戒','沙和尚','白龙马']
console.log(persons)
console.log(persons.length)
</script>
</head>
<body>
</body>
</html>
注意事项:
当JS变量只有声明没有赋值的时候,去调用,那么undefined
当JS根本没有这个变量的时候,去调用,那么报错 arr is not defined
通过数组的索引获取指定的元素
var persons=['孙悟空','唐僧','猪八戒','沙和尚','白龙马']
//(索引从0开始)
console.log(persons[0])//孙悟空
console.log(persons[1])//唐僧
//如果指定的索引不在合法的范围之内,则会返回undefined
console.log(persons[5])
给数组存储数据: 通过下标来存储数据
语法: 数组名[下标] = 值;
var persons=['孙悟空','唐僧','猪八戒','沙和尚','白龙马']
//为数组中指定位置的元素赋值
persons[0]='弼马温'
persons[2]='天棚元帅'
persons[5]='白骨精'
persons[6]='雷公'
persons[7]='电母'
清空数组
// 1.为原始数组重新赋值一个空的数组
persons=[]
console.log(persons)
// 2.为数组的length属性赋值为0
persons.length=0
console.log(persons)
遍历数组
遍历:遍及所有,对数组的每一个元素都访问一次就叫遍历。
数组遍历的基本语法:
for(var i = 0; i < arr.length; i++) {
// 数组遍历的固定结构
}
var persons=['孙悟空','唐僧','猪八戒','沙和尚','白龙马']
//获取数组中的每一项,并打印(遍历数组)
for (var index = 0; index < persons.length; index++) {
console.log(persons[index])
}
//遍历数组 先打印最后一项
for (var i = persons.length - 1; i >= 0; i--) {
console.log(persons[i])
}
//获取数组中的每一项,并打印(遍历数组)
for (var index in persons) {
console.log(persons[index])
}
数组的赋值:
// 格式:数组名[下标/索引] = 值;
// 如果下标有对应的值,会把原来的值覆盖,如果下标不存在,会给数组新增一个元素。
var color = ['red', 'green', 'blue']
// 把red替换成了yellow
color[0] = 'yellow'
// 把blue替换成了pink
color[2] = 'pink'
// 给数组新增加了一个grey的值
color[3] = 'grey'
console.log(color)
2.4.5 对象类型
Object 类型是一个特殊的类型,我们通常把它称为引用类型或者复杂类型:
其他的数据类型我们通常称之为 “原始类型”,因为它们的值只包含一个单独的内容(字符串、数字或者其他);
Object往往可以表示一组数据,是其他数据的一个集合;
- 对象类型由{}进行定义
- 对象类型中包括属性和方法
- 对象的属性和方法是以键和值对的形式 (key: value)的形式 来定义。
- 多个属性或方法由逗号分隔。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>对象类型</title>
<script>
//1.对象类型由{}进行定义
//2.对象类型中包括属性和方法
//3.对象的属性和方法是以键和值对的形式 (key: value)的形式 来定义。
//4.多个属性或方法由逗号分隔。
var person={
name: "李四",
age: 22,
height:175,
sex:'男',
eat: function () {
alert("炫大米饭")
},
sleep: function () {
alert("熬夜")
},
gaming: function(){
alert('玩游戏')
},
}
//获取对象的属性值 对象名.属性名(key)
// 对象名['属性名']
console.log(person.name)
console.log(person.age)
console.log(person["name"])
console.log(person["age"])
// 当访问一个对象中不存在的属性时会返回undefined
console.log(person.address)
//调用对象中的方法 对象名.方法名()
person.eat()
person.gaming()
</script>
</head>
<body>
</body>
</html>
2.4.6 空(Null)
Null也是一个只有一个值的数据类型,它的值就是null,任何变量只要给其赋值为null的话这个变量的数
据类型就是Null类型。
可以通过将变量的值设置为 null 来清空变量。
2.4.7 未定义(Undefined)
这个值表示变量不含有值或未声明。
它的值只有一个,那就是undefined。
在声明变量时如果没有将变量赋值的话这个变量也是属于Undefined类型的。
如果一个变量没有声明就直接去访问解释器会报错,如果使用typeof返回的结果是"undefined"。
Null和Undefined的区别:
Null 已定义,并初始化为null。
Undefined:未定义,或者未初始化 。
2.5 typeof运算符
typeof运算符可以查询数据类型:
-
其返回可能值有:undefined,boolean,number,string、object以及function.
-
可以使用typeof(变量名)查询数据类型
var age = 18;
console.log(typeof age); // 查询到的数据类型是'number'
2.6 数据类型转换
2.6.1 转换成字符串类型
- toString()
var str = "Hello World";
var num = 120.2;
var n = null;
var un;
var bl = true;
var arr = [1, 2, 3, 5];
var obj = { name: "张三" };
function fn1() { }
//toString()
// 把数值转换为字符串类型
console.log(typeof num.toString())
// 把空类型转换为字符串类型
// 空类型没有这个方法,typeof返回object,null如果调用了toString()方法会直接报错
// console.log(typeof n.toString());
// 把未定义类型转换为字符串类型
// 未定义类型没有这个方法,typeof返回undefined,undefined如果调用了toString()方法会直接报错
// console.log(un.toString())
// 把布尔、数组、对象、函数转换为字符串类型
console.log(typeof bl.toString());
console.log(typeof arr.toString());
console.log(typeof String(obj));
//通过这行代码,我们可以得出结论: 函数也是对象
console.log(typeof fn1.toString());
- String()
// String()函数存在的意义:有些值没有toString(),这个时候可以使用String()。
//比如:undefined和null使用String()方法不会报错
// 把数值转换为字符串类型
var num = 18;
console.log(String(num));
// 把布尔转换为字符串类型
var isRight = true;
console.log(String(isRight));
// 把空类型转换为字符串类型
var a = null;
console.log(typeof String(a));
- 拼接字符串方式
num + “”
当 + 两边一个操作符是字符串类型,一个操作符是其它类型的时候,会先把其它类型转换成字符串再进行字符串拼接,返回字符串
//拼接字符串方式
console.log(num+"")
console.log(typeof (num+""))
2.6.2 转换成数值类型
- Number()
// Number()可以把任意值转换成数值,如果要转换的字符串中有一个不是数值的字符,返回NaN
var num1 = '123'
console.log(Number(num1))//123
console.log(typeof Number(num1))//number
var num1 = 'abc'
console.log(Number(num1))//NaN
console.log(typeof Number(num1))//number
var num1 = true
console.log(Number(num1))//1
console.log(typeof Number(num1))//number
- parseInt()
var str = '123'
var isRight = false;
console.log(parseInt(str))//123
console.log(typeof parseInt(str))//number
// parseInt 无法把布尔类型转换成数值类型 返回的结果是NaN
console.log(parseInt(isRight))//NaN
console.log(typeof parseInt(str))//number
// parseInt在转换字符串的时候,如果遇到数字就会转换数字,如果遇到非数字就会返回
var num = '123'
console.log(parseInt(num))//123
console.log(typeof parseInt(num))//number
var num = 'abc'
console.log(parseInt(num))//NaN
console.log(typeof parseInt(num))//number
var num = '123abc'
console.log(parseInt(num))//123
console.log(typeof parseInt(num))//number
// 如果字符串中第一个字符是非数字 此时返回NaN
var num = 'abc123'
console.log(parseInt(num))//NaN
console.log(typeof parseInt(num))//number
- parseFloat()
//parseFloat()把字符串转换成浮点数
//parseFloat()和parseInt非常相似,不同之处在于parseFloat()可以得到浮点值
var str = '123.67';
console.log(parseFloat(str)); //123.67
console.log(parseInt(str)); // 123
//parseFloat 无法转换布尔类型 返回的是NaN
var isRight = true;
console.log(parseFloat(isRight)); //NaN
- +,-0等运算
var str = '500';
console.log(+str); // 500
console.log(-str); // -500
console.log(str - 0); //500
2.6.3 转换成布尔类型
将各种类型的值转化成Boolean类型的规则如下:
-
Number:任意非0的数值为true,0值和NaN为"false"。
-
String:所有的非空字符串转化为 true;“”(空字符串)转化成false
-
Object的任何非空对象都会转化为 true;
-
在javascript中,只要逻辑表达式不返回undefined不返回null,就都是真的。
var str1 = "Hello World";
var str2 = "";
var num = 120.2;
var n = null;
var un;
var bl = true;
var arr = [];
var obj = {};
function fn1() { }
// 任何非空字符串都转换为true,空字符串转换为false
console.log(Boolean(str1)); //true
console.log(Boolean(str2)); //false
// 任何非0数值都转换为true,0和NaN转换为false
console.log(Boolean(num)); //true
// Null和Undefined都转换为false
console.log(Boolean(n)); //false
console.log(Boolean(un)); //false
// 对象和数组都转换为true
console.log(Boolean(arr)); //true
console.log(Boolean(obj)); //true
console.log(Boolean(fn1)); //true
三. JavaScript运算符和表达式
3.1 基本概念
JavaScript描述了一组用于操作数据值的运算符,包括一元运算符、逻辑运算符、算术运算符、关系运算符
三目运算符及赋值运算符。ECMAScript 中的运算符适用于很多值,包括字符串、数值、布尔值、对象等。
表达式:
表达式由一个或多个操作数通过操作符组合而成,就是由数据和运算符组成的一个式子。
操作数:
表达式中的变量成为操作数;
运算符:
表达式中起运算作用的符号称为运算符;
3.2 算术运算符
算术运算符即算术运算符号。是完成基本的算术运算 符号,就是用来处理四则运算的符号。
算数运算符分为以下:
运算符 | 运算规则 | 范例 | 结果 |
---|---|---|---|
+ | 加法 | 2 + 3 | 5 |
+ | 连接字符串 | ‘中’+‘国’ | ‘中国’ |
- | 减法 | 2 - 3 | -1 |
* | 乘法 | 2 * 3 | 6 |
/ | 除法 | 5 / 2 | 2.5 |
% | 取余数 | 5 % 2 | 1 |
** | 幂 | 2 ** 3 | 8 |
加法运算符
var box = 1 + 2; //等于3
var box = 1 + NaN; //NaN,只要有一个NaN 就为NaN
var box = 100 + '100';//100100,字符串连接符,有字符串就不是加法
var box = '您的年龄是:' + 10 + 20; //您的年龄是:1020,被转换成字符串
var box = 10 + 20 + '是您的年龄'; //30 是您的年龄,没有被转成字符串
var box = '您的年龄是:' + (10 + 20); //您的年龄是:30,没有被转成字符串
减法运算符
var box = 100 - 70; //等于30
var box = -100 - 70 ;//等于-170
var box = -100 - -70; //-30,一般写成-100 - (-70)比较清晰
var box = 1 - NaN; //NaN,只要有一个NaN 就为NaN
var box = 100 - true; //99,true 转成数值为1
var box = 100 -false; //100,false转成数值为0
var box = 100 - ''; //100,''转成了0
var box = 100 - '70'; //30,'70'转成了数值70
var box = 100 - null; //100,null 转成了0
var box = 100 - 'Lee'; //NaN,Lee 转成了NaN
乘法运算符
var box = 100 * 70; //7000
var box = 100 * NaN; //NaN,只要有一个NaN 即为NaN
var box = 100 * true; //100,true 转成数值为1
var box = 100 * ''; //0,''转成了0
var box = 100 * null; //0,null 转成了0
var box = 100 * 'Lee'; //NaN,Lee 转成了NaN
除法运算符
var box = 100 / 70; //1.42....
var box = 100 / NaN; //NaN
var box = 100 / true; //100,true 转成1
var box = 100 / ''; //Infinity,
var box = 100 / null; //Infinity,
var box = 100 / 'Lee'; //NaN
求模运算符(求余数)
var box = 10 % 3; //1,余数为1
var box = 100 % NaN; //NaN
var box = 100 % true; //0
var box = 100 % ''; //NaN
var box = 100 % null; //NaN
var box = 100 % 'Lee'; //NaN
JS里面的算数运算规则:
-
任意数据类型和字符串进行加法运算,都是字符串的拼接
-
任意数据类型和NaN进行四则运算,结果都是NaN
-
当true和false参与运算,true转换为1,false转换为0
-
除+运算外,数值类型字符串参与运算,都转换为数值;但是非数值类型字符参与运算,结果是NaN
-
除+运算外,空字符串转换为0,null转换为0
-
0可以作为除数,得到结果都是无穷大
-
0参与取余运算,得到结果都是NaN
3.3 一元运算符
递增和递减运算符概述:
如果需要反复给数字变量添加或减去1,可以使用递增(++)和递减( – )运算符来完成。
在 JavaScript 中,递增(++)和递减( – )既可以放在变量前面,也可以放在变量后面。
放在变量前面时,我们可以称为前置递增(递减)运算符,
放在变量后面时,我们可以称为后置递增(递减)运算符。
递增和递减运算符必须和变量配合使用。
注:++在前,整体是一个新值,++在后,整体是一个旧值
// 在没有赋值操作,前置和后置是一样的.
// 但在赋值操作时:
// 1.如果递增或递减运算符前置,那么前置的运算符会先累加或累减再赋值,
// 2.如果是后置运算符则先赋值再累加或累减。运算的时候也是一样;
// 后置递增
var a = 1
console.log(a++)//1
console.log(a)//2
// 前置递增
var b = 1
console.log(++b)//2
console.log(b)//2
//简单示例
var a = 1; var b = ++a + ++a; console.log(b);//5
var a = 1; var b = a++ + ++a; console.log(b);//4
var a = 1; var b = a++ + a++; console.log(b);//3
var a = 1; var b = ++a + a++; console.log(b);//4
var a = 5; var b = ++a + a++; console.log(b);//12
var a = 2; var b = a++ + ++a + a++; console.log(b);//2+4+4=10
var a = 1; var b = --a + --a; console.log(b);//-1
var a = 1; var b = --a + a--; console.log(b);//0
var a = 5; var b = --a + a--; console.log(b);//8
var a = 5; var b = a-- + --a; console.log(b);//8
var a = 5; var b = a-- + --a + ++a; console.log(b);//12
3.4 赋值运算符
用来把数据赋值给变量的运算符。
运算符 | 运算规则 | 范例 | 结果 |
---|---|---|---|
= | 赋值 | a=5 | 5 |
+= | 加后赋值 | a=5,a+=2 | 7 |
-= | 减后赋值 | a=5,a-=2 | 3 |
*= | 乘后赋值 | a=5,a*=2 | 10 |
/= | 除后赋值 | a=5,a/=2 | 2.5 |
%= | 取模(余数)后赋值 | a=5,a%=2 | 1 |
**= | 幂后赋值 | a=5,a**=2 | 25 |
var num1=10
num1+=5//等价于num1=num1+5
在JavaScript中,赋值运算符是“=”,其含义就是把赋值运算符右边的数值或表达式的值赋给赋值运算符左边的变量或表达式。
3.5 关系运算符(比较运算符)
比较运算符(关系运算符)是两个数据进行比较时所使用的运算符,会返回一个布尔值(true / false)作为比较运算的结果。
运算符 | 运算规则 | 范例 | 结果 |
---|---|---|---|
== | 相等 | 4 == 3 | false |
!= | 不等于 | 4 != 3 | true |
< | 小于 | 4 < 3 | false |
> | 大于 | 4 > 3 | true |
<= | 小于等于 | 4 <= 3 | false |
<= | 大于等于 | 4 >= 3 | true |
比较原则:
- 若一个是数值字符串,一个是数值,字符串会自动转换成数值进行比较。
- 若两个都是数值字符串,则比较首个数字的大小。
- 布尔值的false和true会转换成0和1。
- 两个操作数都是数值,则数值比较。
- 两个操作数都是字符串,则比较两个字符串对应的字符编码值。
字符转ascii码:用charCodeAt();
在相等和不等的比较上,如果操作数是非数值,则遵循以下规则:
-
一个操作数是布尔值,则比较之前将其转换为数值,false 转成0,true 转成1;
-
一个操作数是字符串,则比较之前将其转成为数值再比较;
-
不需要任何转换的情况下,null 和undefined 是相等的;
-
一个操作数是NaN,则==返回false,!=返回true;并且NaN 和自身不等;
-
在全等和全不等的判断上,比如值和类型都相等,才返回true,否则返回false。
相等运算符 == :判断两个操作数是否相等.不同的数据类型会自动转换为相等的数据类型再做比较
等同运算符=== :全等(值和类型),严格意义的相等,两个操作数的值和他们的类型必须完全一致
// 关系运算符
//==表示比较等于 =表示赋值 ===表示判断全等(值和类型)
console.log(4==3)//false
console.log(3==3)//true
console.log('3'==3)//true
console.log(3===3)//true
console.log('3'===3)//false 值相等,类型不相等
3.6 逻辑运算符
逻辑运算符通常用于布尔值的操作,一般和关系运算符配合使用,有三个逻辑运算符:
逻辑与(AND)、逻辑或(OR)、逻辑非(NOT)。
运算符 | 运算规则 | 范例 | 结果 |
---|---|---|---|
&& | 与:同时为真 | false&&true | false |
|| | 或:一个为真 | false||true | true |
! | 非:取反 | !false | true |
-
逻辑与运算符属于短路操作,如果第一个操作数返回是false,第二个数不管是true 还是false 都返回的false。
-
逻辑或运算符也是短路操作。当第一操作数的求值结果为true,就不会对第二个操作数求值了
-
逻辑非运算符可以用于任何值。它的流程是:先将这个值转换成布尔值,然后取反。
//逻辑与运算
var grades = 100;
var date = 'weekend'
if (grades == 100 && date == 'weekend') {
console.log('出去看电影')
}
else {
console.log('在家写作业')
}
3.7 三目运算符
三目运算符,又叫三元条件运算符
三元条件运算符其实就是后面将要学到的if 语句的简写形式。
根据条件在两个语句中执行其中的一个,使用符号 ?:
语法如下:条件表达式?语句1:语句2
参数说明:
-
条件表达式,结果会被作为布尔值处理
-
语句1:如果条件表达式返回true则执行
-
语句2:如果条件表达式返回false则执行
//三元运算符
var a = 5
var b = 2
var result = a > b ? '对' : '错'
console.log(result)
var age = 20
var result = age >= 18 ? '成年' : '未成年'
console.log(result)
四. javaScript流程控制语句
4.1 语句的定义
在ECMAScript 中,所有的代码都是由语句来构成的。
-
一行代码就是一条简单语句。形式上可以是单行语句,或者由一对大括号“{}”括起来的复合语句
-
复合语句包含若干条简单语句,它可以作为一个单行语句处理。复合语句也称为语句块。
4.2 流程控制语句分类
任何复杂的程序逻辑都可以通过”顺序”、”条件(分支)”和”循环”三种基本的程序结构来实现。
-
顺序程序结构就是从上往下顺序执行语句;程序默认就是由上到下顺序执行的
-
条件(分支)程序结构就是根据不同的情况执行不同的语句;
-
循环程序结构就是某些语句要循环执行多次。
4.3 条件语句
if语句即条件判断语句,一共有三种格式:
-
单分支的条件语句;
-
双分支的条件语句;
-
多分支的条件语句。
条件语句用于基于不同的条件来执行不同的动作。
4.3.1 单分支的条件语句
if(){} 语句 - 只有当指定条件为 true 时,使用该语句来执行代码:
//语法
if (/* 条件表达式 */) {
// 执行语句
}
//示例
//if语句
var num=20
if(num>15){
console.log('该数字大于15')
}
console.log(num)
注意:
-
放在if之后的括号里的返回值只能是true或false。
-
如果表达式的值为true,则执行语句;如果表达式的值为false,则什么也不执行。
-
花括号括起来的语句块可以只有一行语句,也可以由多行代码构成。建议都加花括号
4.3.2 双分支条件语句
if()…else 语句 - 当条件为 true 时执行语句1,当条件为 false 时执行语句2
//语法
if (/* 条件表达式 */){
// 成立执行语句
} else {
// 否则执行语句
}
//示例
//if-else语句
var age=15
if(age>=18){
console.log('成年')
}
else{
console.log('未成年')
}
4.3.3 多分支的if条件语句
if()…else if()…else 语句 - 使用该语句来选择多个代码块之一来执行.
//语法
if (/* 条件1 */){
// 成立执行语句
} else if (/* 条件2 */){
// 成立执行语句
} else if (/* 条件3 */){
// 成立执行语句
} else {
// 最后默认执行语句
}
//示例
//if-else if-else语句
var scores=55
if(scores>=90){
console.log('优秀')
}
else if(scores>=80){
console.log('良好')
}
else if(scores>=70){
console.log('一般')
}
else if(scores>=60){
console.log('及格')
}
else {
console.log('挂科')
}
注:if语句()中的表达式会自动转换成布尔值。
满足条件即执行对应语句,然后语句结束;如果都不满足,则执行else语句块;else语句块可以不存在
4.3.4 switch多条件选择语句
-
switch语句又称开关语句,它与多重if语句类似,前者用于等值判断,后者用于区间值和等值判断
-
switch语句的作用是根据表达式的值,跳转到不同的语句。
-
switch 语句用于基于不同的条件来执行不同的动作。
//语法
switch (expression) {
case 常量1:
语句;
break;
case 常量2:
语句;
break;
case 常量3:
语句;
break;
…
case 常量n:
语句;
break;
default:
语句;
break;
}
switch多条件选择语句:
-
首先设置表达式,随后表达式的值会与结构中的每个case 的常量表达式做比较。
-
如果存在匹配,则与该case 关联的代码块会被执行。使用 break 来阻止代码自动地向下一个 case 运行。
-
default 关键词来规定匹配不存在时做的事情,当没有匹配的值时,执行default下的语句。
-
switch 语句在比较值时使用的是全等操作符, 因此不会发生类型转换
//示例
//给定一个数字,输出星期几
var num=9
switch (num) {
case 1:
console.log('星期一')
break;
case 2:
console.log('星期二')
break;
case 3:
console.log('星期三')
break;
case 4:
console.log('星期四')
break;
case 5:
console.log('星期五')
break;
case 6:
console.log('星期六')
break;
case 7:
console.log('星期日')
break;
default:
console.log('输入日期不在合法范围内')
break;
}
4.4 循环程序结构
循环程序的结构有三要素:循环的初始值、循环条件(循环的结束值)和循环的迭代,
所谓循环的迭代就是如何从初始值到结束值,一个循环程序还有包含一个循环体。
4.4.1 while语句
while循环会在指定条件为真时循环执行代码块,它是一种先判断,后运行的循环语句,
必须满足条件了之后,方可运行循环体。用于不太确定循环次数的场合。
//语法
// 当循环条件为true时,执行循环体,
// 当循环条件为false时,结束循环。
while (循环条件) {
//循环体
}
//示例
//打印1-100之间所有的数字
var num=1
while(num<=100){
console.log(num)
num++
}
4.4.2 do…while循环
-
do…while 循环是 while 循环的变体,
-
在检查条件是否为真之前,该循环会至少执行一次do下的代码块(循环体)
-
如果条件为真的话,就会重复这个循环,否则退出该循环体。
-
常用于至少执行一次循环体,再判断要不要继续循环的场合。
语法
do {
// 循环体;
} while (循环条件);
//示例
//求100以内所有数的和
var num=1
var sum=1
do{
sum+=num
num++
}
while(num<=100)
console.log(sum)
4.4.3 for语句
-
for 语句是应用最广泛、功能最强的一种循环语句。大部分情况下,for 循环可以代替 while和do while 循环。
-
for 语句是一种在程序执行前就要先判断条件表达式是否为真的循环语句。
-
假如条件表达式的结果为假,那么它的循环语句根本不会执行。
-
for 语句通常使用在知道循环次数的循环中。
//语法
for(条件表达式1; 条件表达式2; 条件表达式3) {
语句块;
}
//示例
//打印1-100之间所有数
for(i=1;i<=100;i++){
console.log(i)
}
for 循环中 3 个条件表达式的含义如下:
表达式 | 形式 | 功能 | 举例 |
---|---|---|---|
条件表达式1 | 赋值语句 | 循环变量的初始部分,为循环变量赋初值 | i=1 |
条件表达式2 | 条件语句 | 循环结构的循环条件 | i<=100 |
条件表达式3 | 迭代语句 | 循环结构的迭代部分,通常用来修改循环变量的值 | i++ |
for 关键字后面括号中的 3 个条件表达式必须用“;”隔开。
for 循环语句执行的过程为:
-
首先执行条件表达式 1,进行初始化,
-
然后判断条件表达式 2,的值是否为true,如果为 true,则执行循环体语句块;否则直接退出循环。
-
最后执行条件表达式 3,改变循环变量的值,至此完成一次循环。
-
接下来进行下一次循环,直到条件表达式 2 的值为 false,才结束循环,其运行
for 循环和 while、do while 循环不一样:
- 由于 while、do while 循环的循环迭代语句紧跟着循环体,因此如果循环体不能完全执行,
(如使用 continue 语句来结束本次循环),则循环迭代语句不会被执行。
- 但for 循环的循环迭代语句并没有与循环体放在一起,
因此不管是否使用 continue 语句来结束本次循环,循环迭代语句一样会获得执行。
注:如果循环体只有一行语句,那么循环体的大括号可以省略。
4.4.4 for…in语句
for…in 语句用于遍历数组或者对象的属性
for…in 循环中的代码每执行一次,就会对数组的元素或者对象的属性进行一次操作。
for…in遍历数组
var arr = [13, 21, 34, 42, 53, 63];
//1.for循环遍历数组
for (var i = 1; i < arr.length; i++) {
console.log(arr[i])
}
//2.for..in循环遍历数组
for (var i in arr) {
console.log(arr[i])
}
for…in遍历对象
var arr = [13, 21, 34, 42, 53, 63];
//for..in遍历对象
var person = {
name: "jack",
age: 12,
height: 178
}
for(var per in person){
console.log(person[per])
}
-
在JavaScript语言中,支持循环语句的相互嵌套,即在一个循环语句中嵌套另一个循环语句,
-
需要注意的是,break和continue语句用在循环嵌套中,这两条语句只对离它最近的循环语句有效。
4.5 跳转语句
-
break:立即跳出整个循环,即循环结束,开始执行循环后面的内容(直接跳到大括号)
-
continue:立即跳出当前循环,继续下一次循环(跳到i++的地方)
-
continue 语句只能用在循环中;break能用在循环或 switch 中。
4.6 调试
- 在浏览器中使用f12进入开发者模式,然后在源代码页面使用f5选择断点,再使用f9或者右侧工具进行调试
- 再要调试的代码前使用debugger选择断点,然后进入开发者模式调试
五. JavaScript函数
5.1 javaScript函数的定义
函数概念
函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块。
(把一段相对独立的具有特定功能的代码块封装起来,形成一个独立实体,就是函数)
函数的作用就是封装一段代码,将来可以重复使用。
函数就是包裹在花括号中的代码块:
函数语法
- 函数声明
function 函数名(参数列表){
// 函数体
}
- 函数表达式
var fn(自定义) = function () {
// 函数体
}
特点:
函数声明的时候,函数体并不会执行,只要当函数被调用的时候才会执行。
函数一般都用来干一件事情,函数名称一般使用动词
5.2 JavaScript声明式函数的应用
函数的应用是先声明一个函数,再调用该函数。
5.2.1 函数的调用
- 调用函数的语法
函数名();
- 函数调用的特点
函数体只有在调用的时候才会执行,调用需要()进行调用。
可以调用多次(重复使用)
在JavaScript中,调用函数时,如果没有返回值,就直接用函数方法名()调用。
如果有参数,则必须给每个参数赋值,函数方法名(参数值),如果还有返回值,可以用一个变量来存储这个值。
函数的参数
函数内部是一个封闭的环境,可以通过参数的方式,把外部的值传递给函数内部。
带参数的函数声明语法:
function 函数名(var1, var2...) {
// 函数体
}
5.2.2 函数的参数
形参和实参
-
形式参数:在声明一个函数的时候,为了函数的功能更加灵活,有些值是固定不了的,对于这些固定不了的值。我们可以给函数设置参数。这个参数没有具体的值,仅仅起到一个占位置的作用,我们通常称之为形式参数,也叫形参。
-
实际参数:如果函数在声明时,设置了形参,那么在函数调用的时候就需要传入对应的参数,我们把传入的参数叫做实际参数,也叫实参。
注:同一个函数,形参和实参是一一对应的。
如何区分实参和形参?
- 出现的地方不一样,形参是在函数的声明中,实参出现在函数的调用中。
- 代表的意义不一样,形参是声明一个变量,实参是该变量的值。
5.2.3 函数的返回值
当函数执行完的时候,并不是所有时候都要把结果打印。我们期望函数给我一些反馈
这个时候可以让函数返回一些东西,也就是返回值。函数通过return返回一个返回值。
返回值语法
//声明一个带返回值的函数
function 函数名(形参1, 形参2, 形参3...) {
//函数体
return 返回值;
}
//可以通过变量来接收这个返回值
var 变量 = 函数名(实参1, 实参2, 实参3...);
函数的调用结果就是返回值,因此我们可以直接对函数调用结果进行操作。
返回值详解:
-
如果函数没有显式的使用 return语句 ,那么函数有默认的返回值:undefined。
-
如果函数使用 return语句,那么跟在return后面的值,就成了函数的返回值。
-
如果函数使用 return语句,但是return后面没有任何值,那么函数的返回值也是:undefined。
-
函数使用return语句后,函数在执行完 return 语句之后会停止并立即退出,return后面的所有其他代码都不会再执行。
推荐的做法是要么让函数始终都返回一个值,要么永远都不要返回值。
5.2.4 函数是一种数据类型
函数的类型是function
function fn() {}
console.log(typeof fn);
函数作为参数:因为函数也是一种类型,可以把函数作为另一个函数的参数,在另一个函数中调用
函数做为返回值:因为函数是一种类型,所以可以把函数可以作为返回值从函数内部返回。
function fn(b) {
var a = 10;
//函数做为返回值
return function () {
alert(a+b);
}
}
fn(15)();
5.3 javaScript arguments对象
-
JavaScript中,arguments对象是比较特别的一个对象,实际上是当前函数的一个内置属性。
-
所有函数都内置了一个arguments对象,arguments对象中存储了传递的所有的实参。
-
arguments是一个伪数组,因此就可以进行遍历。
5.4 javaScript函数作用域
变量从作用域的角度划分,分为两种:
-
局部变量
-
全局变量
作用域就是变量可以起作用的范围
5.4.1 局部变量
-
在JavaScript函数内部声明的变量是局部变量,所以只能在函数内部访问它,该变量的作用域是局部的。
-
可以在不同的函数中使用名称相同的局部变量因为只有声明过该变量的函数才能识别出该变量
-
只要函数运行完毕,局部变量就会被删除。
function hello() {
//在函数内部声明了一个num,此时num为局部变量,只能在函数内部使用
var num = 2
console.log(num);
}
5.4.2 全局变量
在函数外声明的变量是全局变量,网页上的所有脚本和函数都能访问它。
注:如果没有使用var声明变量,该变量将被自动作为全局变量声明,不推荐使用。
5.4.3 变量的生命周期
-
JavaScript 变量的生命期从它们被声明的时间开始。
-
局部变量会在退出作用域之后会销毁。
-
全局变量会在关闭网页或浏览器才会销毁。
5.4.4 局部变量和全局变量的区别
-
声明位置不同:局部变量声明在函数内部。全局变量声明在函数外部。
-
作用域不一样:局部变量只在某一个局部范围有效,比如函数内部。
全局变量在整个页面有效,网页上的所有脚本和函数都能访问它。
-
生命周期不一样:局部变量会在函数运行以后被删除,全局变量会在页面关闭后被删除。
5.4.5 块级作用域
块级作用域:任何一对花括号({和})中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的
5.4.6 作用域链
只有函数可以制造作用域结构, 只要是代码,至少有一个作用域, 即全局作用域。
如果代码中有函数,那么这个函数就构成另一个作用域。
如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域。
将这样的所有的作用域列出来,可以有一个结构: 函数内指向函数外的链式结构。就称作作用域链。
5.5 匿名函数
匿名函数,就是没有名字的函数。
匿名函数:有关键词 function, 有小括号,有大括号,就是没有函数名。
如何执行匿名函数
-
把它放进一个变量里,这个变量就相当于函数名。匿名函数,就变成有“名”函数了,这种方式称之为函数字面量。
var myfun=function(a,b){ console.log(a+b); } myfun(10,20)
-
不要名字,直接执行~!-- 这么做可以在内部形成局部变量和局部函数,防止全局污染。
注意: 使用改写法一定要注意添加分号 1. //(匿名函数)(); (function(a,b){ console.log(a+b); })(10,20); 2. //(匿名函数() ); (function(a,b){ console.log(a+b); }(20,30)); 3. //在function前面加一元操作符号 !function (a, b) { console.log(a + b); }(10, 30); 4. //在function前面添加 new 关键词 new function (a, b) { console.log(a + b); }(10, 30);
-
利用事件去调用。
<input type="button" value="点我提示信息" id="btn1"> <script> var btn = document.getElementById('btn1') btn.onclick = function () { console.log('你点了我'); } </script>
-
作为对象的方法调用
var boy = { name: '小黑', eat: function (footname) { console.log('我喜欢吃'+footname); } } boy.eat('炸鸡'+'大肘子')
-
作为另一个函数的参数。
function eat(fn) { console.log('先吃饭再说'); // 在此处调用fn函数 fn() } //有名函数做参数 // function pay(){ // console.log('今天吃饭我请客'); // } // eat(pay) //匿名函数做参数 eat(function () { console.log('今天aa'); })
5.6 构造函数
通过new 函数名() 来实例化对象的函数叫构造函数。任何的函数都可以作为构造函数存在。
构造函数与普通函数之分,主要从功能上进行区别的:
-
构造函数的主要功能为初始化对象,特点是和new一起使用。
-
new就是在创建对象,从无到有,构造函数就是在为初始化的对象添加属性和方法。
-
构造函数定义时首字母大写(规范)。
对new理解:new 申请内存, 创建对象,当调用new时,后台会隐式执行new Object()创建对象。所以,通
过new创建的字符串、数字是引用类型,而是非值类型。
//peerson为一个抽象的概念,可以理解为是一个类型
function person(id,name,age){
//this指代当前对象
this.id=id
this.name=name
this.age=age
this.say=function(){
console.log('我是'+name+ ',我'+age+'岁了');
}
}
//p1是一个具体的概念,可以理解为是一个类型的实例
var p1=new person(1001,'张三',18)
console.log(p1);
//调用方法
p1.say()
var p2=new person(1002,'李四',28)
console.log(p2);
//调用方法
p2.say()
5.7 回调函数
字面上的理解,回调函数就是一个参数,将这个函数作为参数传到另一个函数里面
当那个函数执行完之后,再执行传进去的这个函数。这个过程就叫做回调。
// 主函数
function gohome(fn){
console.log('打的回家');
console.log('我到家了');
//执行回调函数
fn()
}
function sendsms(){
console.log('给你发信息');
}
gohome(sendsms)
// gohome(function(){
// console.log('我们不合适');
// })
主函数不用等待回调函数执行完,可以接着执行自己的代码。
所以一般回调函数都用在耗时操作上面。比如ajax请求,比如处理文件等。
5.8 预解析
JavaScript代码的执行是由浏览器中的JavaScript解析器来执行的。
JavaScript解析器执行JavaScript代码的时候,分为两个过程:预解析过程和代码执行过程。
什么是预解析?
-
浏览器在执行JS代码的时候会分成两部分操作:预解析以及逐行执行代码
-
浏览器不会直接执行代码, 而是加工处理之后再执行,
-
这个加工处理的过程, 我们就称之为预解析
预解析过程:
- 把变量的声明提升到当前作用域的最前面,只会提升声明,不会提升赋值。
- 把函数的声明提升到当前作用域的最前面,只会提升声明,不会提升调用。
- 先提升var,再提升function。
<script>
var a=100
console.log(a);
console.log(b);
//如果一个代码段中出现了报错,则后续该代码段中的剩余代码将不会执行
console.log('hello');
</script>
<script>
console.log(a);
var a=100
// 预解析后
var a
console.log(a);
a=100
show()
function show(){
console.log('hello');
}
// 预解析后
function show(){
console.log('hello');
}
show()
//js会经过预解析后再去执行
</script>
变量提升
变量提示原则:
1、所有声明都会被提升到作用域的最顶上;
2、同一个变量声明只进行一次,并且因此其他声明都会被忽略;
3、函数声明的优先级优于变量声明,且函数声明会连带定义一起被提升。
变量提升:
把变量声明提升到函数的顶部,但是变量赋值不会提升。
注意:变量未声明,直接使用,输出‘变量 is not defined。
函数提升:
-
函数提升会将函数声明连带定义一起提升。
-
在JavaScript中函数的创建方式有三种:函数声明、函数表达式(函数字面量)、函数构造法(动态的,匿名的)。
-
只有函数声明创建的函数会执行函数提升,字面量定义的函数(实质为变量+匿名函数)会执行变量提升。
5.9 防止全局污染
全局污染问题
JavaScript 可以随意定义保存所有应用资源的全局变量。
但全局变量可以削弱程序灵活性,增大了模块之间的耦合性。
在多人协作时,如果定义过多的全局变量有可能造成全局变量冲突,也就是全局变量污染问题。
解决全局污染
方式一:定义全局变量命名空间,只创建一个全局变量,并定义该变量为当前应用容器,把其他全局变量追加在该命名空间下。
var my ={} //唯一的全局变量
my.name={
big_name:'张三',
small_name:'三'
}
var you={}
you.name={
big_name:'李四',
small_name:'四'
}
console.log(my.name.small_name);
console.log(you.name.small_name);
方式二:利用匿名函数将脚本包裹起来
(function () {
var temp = {}
// 把两个变量赋值给temp
temp.name = '张三'
temp.age = 18
// small_name='李四'
// temp.getname=function(){
// return small_name
// }
//把tmep赋值给全局变量people
window.people = temp
}())
console.log(people.age)
// console.log(people.getname())
六. javaScript对象
6.1 对象的概念
为什么要有对象?
函数的参数如果特别的话,可以使用对象简化
JavaScript中的对象
-
JavaScript语言没有类,所以使用构造函数作为对象的模板
-
构造函数:就是专门用来生成对象的函数,它提供模板,作为函数的基本结构
-
一个构造函数可以生成多个对象,这些对象都有相同的属性和行为,属性值可以不同。
-
JavaScript没有类和接口,只有对象。对象是”无序属性的集合,其属性包含基本值,对象或者函数。
-
对象object是JavaScript的核心概念,也是最重要的数据类型。JavaScript的所有数据都可以被视为对象
-
对象是一个容器,封装了属性和方法:属性就是对象的静态状态,对象就是对象的动态行为。
-
对象的行为和特征:特征在对象中用属性来表示,行为在对象中用方法来表示
6.2 对象的使用
6.2.1 对象的创建方式
对象字面量
var hero={
name:'黄忠',
weapon:'弓箭',
equipment:['头盔','靴子','盔甲'],
bolld:100,
attack:function(){
//this表示当前对象
console.log(this.name+':射箭');
},
run:function(){
console.log(this.name+',加速跑');
}
}
console.log(hero.name);
console.log(hero.equipment);
hero.attack()
hero.run()
new Object()创建对象
var hero=new Object()
console.log(hero.name); //undefind
//动态为该对象添加属性和方法
hero.name='关羽';
hero.weapon='青龙偃月刀';
hero.equipment=['头盔','靴子','赤兔马'];
hero.blood=100;
hero.attack=function(){
console.log(this.name+':射箭');
}
hero.run=function(){
console.log(this.name+':加速跑');
}
//使用属性
console.log(hero.name);
console.log('武器:'+ hero.weapon);
//调用方法
hero.attack()
hero.run()
工厂函数创建函数
function createhero(name,weapon,Mounts){
var hero=new Object();
//属性
hero.name=name;
hero.weapon=weapon;
hero.Mounts=Mounts;
//方法
hero.attack=function(){
console.log(this.name+'使用'+this.weapon+'攻击');
}
hero.run=function(){
console.log(this.name+'使用'+this.Mounts+'行军');
}
return hero
}
var hero1=createhero('关羽','青龙偃月刀','赤兔马')
var hero2=createhero('刘备','雌雄双股剑','的卢马')
//使用属性
alert(hero1.name +':武器是'+ hero1.weapon+',坐骑是'+ hero1.Mounts);
alert(hero2.name +':武器是'+ hero2.weapon+',坐骑是'+ hero2.Mounts);
//调用方法
hero1.attack()
hero1.run()
hero2.attack()
hero2.run()
自定义构造函数
function hero(name,weapon,equipment,blood){
//定义相关属性
//this指向了当前对象
this.name=name
this.weapon=weapon
this.equipment=equipment
this.blood=blood
//定义相关方法
this.attack=function(){
console.log(this.name+':攻击');
}
this.run=function(){
console.log(this.name+':加速跑');
}
}
var hero1=new hero('张飞','丈八蛇矛',['头盔','铠甲','靴子'],100)
var hero2=new hero('吕布','方天画戟',['头盔','铠甲','靴子'],100)
//使用属性
console.log(hero1);
console.log(hero2);
console.log(hero1.name);
console.log(hero2.equipment);
//调用方法
hero1.attack()
构造函数有个缺点,就是对象的方法放在了构造函数内部,这样每创建一个方法就会需要多占用一些内存
可以使用prototype属性,用来存放对象的方法
function student(name,age,id){
this.name=name;
this.age=age;
this.id=id;
}
// 将方法放在对象的prototype属性中
student.prototype={
work:function(skill){
alert(this.name+'做'+skill+'开发相关的工作')
},
classid:'前端班'
}
var stud1=new student('李明',20,203230);
var stud2=new student('麦克',22,203231);
console.log(stud2.work==stud1.work);//true 节省了内存空间
stud1.work('java')
stud2.work('php')
console.log(stud1.id);
console.log(stud2.id);
6.2.2 属性和方法
如果一个变量属于一个对象,该变量就称之为该对象的一个属性,属性一般是名词,用来描述事物的特征。
如果一个函数属于一个对象,该函数就称之为该对象的一个方法,方法是动词,描述事物的行为和功能。
6.2.3 关键字详解
new
new在执行时会做四件事情
-
new会在内存中创建一个新的空对象
-
new 会让this指向这个新的对象
-
执行构造函数的目的:给这个新对象加属性和方法
-
new会返回这个新对象
this
this的几个特点
-
函数在定义的时候this是不确定的,只有在调用的时候才可以确定
-
一般函数直接执行,内部this指向全局window
-
函数作为一个对象的方法,被该对象所调用,那么this指向的是该对象
-
构造函数中的this其实是一个隐式对象,类似一个初始化的模型,所有方法和属性都挂载到了这个隐式对象身上,后续通过new关键字来调用,从而实现实例化
6.2.4 对象的使用方法
对象属性的使用:
- 用 . 符号访问对象属性
- 用数组的方式,即用[“属性名称”]
对象方法的使用:
- 对象名.方法名()来调用
遍历对象的属性
通过for…in语法可以遍历一个对象
var obj = {
name: '张三',
age: 18,
sex: true,
};
for(var key in obj) {
console.log(key + "==" + obj[key]);
}
删除对象的属性
function fun() {
this.name = 'mm';
}
var obj = new fun();
console.log(obj.name); // mm
//删除对象的属性
delete obj.name;
console.log(obj.name); // undefined
简单类型和复杂类型的区别
基本类型又叫做值类型,复杂类型又叫做引用类型
值类型:简单数据类型,基本数据类型,在存储时,变量中存储的是值本身,因此叫做值类型
引用类型:复杂数据类型,在存储时,变量中存储的仅仅是地址,因此叫做引用数据类型
为了方便理解和学习,引入堆和栈
堆和栈空间分配区别:
1、栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。
2、堆(操作系统): 存储复杂类型(对象),一般由程序员分配释放, 若程序员不释放,由垃圾回收机制回收。
七. javascular内置对象
JavaScript中的对象分为三种:内置对象,自定义对象,浏览器对象
内置对象的方法很多,我们要学习内置对象提供的常用方法(结合文档学习)
如何学习一个方法?
- 方法的功能
- 参数的意义和类型
- 返回值的意义和类型
- 使用demo进行测试
7.1 Array对象
检测一个对象是否是数组:
- instanceof
var arr =[1,2,3,4]
console.log(arr instanceof Array);//结果为true
- Array.isArray() HTML5中提供的方法,有兼容性问题
var arr =[1,2,3,4]
console.log(Array.isArray(arr));//结果为true
Array对象方法
- 读取数据:可以使用索引查询获取数组元素和添加数组元素;
// 输出数组长度
// console.log(arr.length);
// 输出数组中的某一位
// console.log(arr[5]);
//添加数组元素
var arr=[1,2,3]
arr[3]=4
console.log(arr);//[1, 2, 3, 4]
- 添加数据:使用**push()**方法将新元素添加到数组尾部,返回值为新数组的长度
var arr = [1,2,3]
//给数组添加新元素
arr.push('张三')
console.log(arr);
//将数组元素添加给新数组
var arr1=[]
arr1.push(arr[3])
console.log(arr1);
console.log(arr);
- 删除数据:可以使用delete运算符删除指定的元素;
// delete删除数组元素,被删除的元素在数组中显示为空
var arr = [1,2,3,4,5,6,7,8,9]
delete arr[5]
console.log(arr);
- 删除末尾元素 : **pop()**方法,该方法会返回删除的元素;
var arr = [1,2,3,4,5,6,7,8,9]
console.log(arr.pop());//返回删除的元素
arr.pop()
console.log(arr);
- 删除顶端的元素:**shift()**方法;
var arr = [1,2,3,4,5,6,7,8,9]
//shift()删除顶端元素;该方法会返回删除的元素;
console.log(arr.shift());//返回删除的元素;
arr.shift()
console.log(arr);
- 在数组顶端添加元素 : **unshift()**方法,返回值为新数组的长度;
var arr = [1,2,3,4,5,6,7,8,9]
// unshift()在数组顶端添加元素,返回值为新数组的长度;
console.log(arr.unshift(5));//返回值为新数组的长度;
arr.unshift(5)
console.log((arr));
- 字符转换:**toString()**方法将数组表示为字符串;
var arr = [1,2,3,4,5,6,7,8,9]
// toString()将数组转换为字符串,元素之间通过,分隔
console.log(arr.toString());
//将一个字符串数组输出为|分割的形式
function getarr (arr,sep){
var str=arr[0]
for(i=1;i<arr.length;i++){
str+= sep+arr[i]
}
return str
}
var arr=[1,2,3,4,5,6,7,8,9]
console.log(getarr(arr,'|'));
- 数组转字符串:join方法输出数组元素,输出结果会转换成字符串;
var arr = [1,2,3,4,5,6,7,8,9]
// join()输出结果会转换成字符串,元素直接通过字符分隔
console.log(arr.join('任意字符'));
//将一个字符串数组输出为|分割的形式
var arr = [1,2,3,4,5,6,7,8,9]
console.log(arr.join('|'));
- 数组逆序:**reverse()**方法颠倒数组元素的顺序;返回值为逆序后的新数组;
var arr = [1,2,3,4,5,6,7,8,9]
// reverse()颠倒数组元素的顺序;返回值为逆序后的新数组
console.log(arr.reverse());
arr.reverse()
console.log(arr);
- 数组排序:**sort()**方法可以实现数组排序;
var arr = [1,2,3,4,5,6,7,8,9]
// sort()方法可以实现数组排序;
// sort执行之后会改变原始数组
//升序排列
arr.sort(function(a,b){
return a-b;})
console.log(arr);
//降序排列
arr.sort(function(a,b){
return b-a;})
console.log(arr);
//升序排列
arr.sort((a,b)=>a-b)
console.log(arr);
//降序排列
arr.sort((a,b)=>b-a)
console.log(arr);
- 扩充数组:**concat()**方法 将多个数组的元素合并为一个新的数组;
var arr1=[1,2,3];
var arr2=[4,5,6];
var arr3=[7,8,9];
var arr= arr1.concat(arr2,arr3)
console.log(arr);
- splice方法:删除、替换、插入元素,会更改原数组;
// splice方法:删除、替换、插入元素,会更改原数组;
// 第一参数为起始位置索引;
// 第二参数为切取元素个数;(从起始位置开始切取,包括起始位置)
// 第三个参数为插入元素,可选项;
var arr=[1,2,3,4,5,6]
arr.splice(2,0,"zhangsan")
console.log(arr);
- 截取数组:slice() 切取数组的一段元素;
var arr=[1,2,3,4,5,6]
//切取部分作为新数组返回,不会对原数组改变。
// 第一参数为起始位置索引(包含)。
// 第二参数为结束位置索引(不包含),注意区分splice。
//若省略第二个参数则直接切取到结尾
console.log(arr.slice(1,4));
- valueOf() 返回数组对象本身
7.2 Date对象
Date是JavaScript的内置对象,系统在Date对象中封装了与日期和时间相关的属性和方法。
Date使用UTC1970年1月1日0时开始经过的毫秒来存储时间。
Date对象方法
通过使用针对日期对象的方法,我们可以很容易地对日期进行操作
方法名 | 作用 |
---|---|
getDate() | 从 Date 对象返回一个月中的某一天 (1 ~ 31)。 |
getDay() | 从 Date 对象返回一周中的某一天 (0 ~ 6)。 |
getFullYear() | 从 Date 对象以四位数字返回年份。 |
getHours() | 返回 Date 对象的小时 (0 ~ 23)。 |
getMilliseconds() | 返回 Date 对象的毫秒(0 ~ 999)。 |
getMinutes() | 返回 Date 对象的分钟 (0 ~ 59)。 |
getMonth() | 从 Date 对象返回月份 (0 ~ 11)。 |
getSeconds() | 返回 Date 对象的秒数 (0 ~ 59)。 |
getTime() | 返回 1970 年 1 月 1 日至今的毫秒数。 |
setDate() | 设置 Date 对象中月的某一天 (1 ~ 31)。 |
setFullYear() | 设置 Date 对象中的年份(四位数字)。 |
setHours() | 设置 Date 对象中的小时 (0 ~ 23)。 |
setMilliseconds() | 设置 Date 对象中的毫秒 (0 ~ 999)。 |
setMinutes() | 设置 Date 对象中的分钟 (0 ~ 59) |
setMonth() | 设置 Date 对象中月份 (0 ~ 11)。 |
setSeconds() | 设置 Date 对象中的秒钟 (0 ~ 59)。 |
setTime() | 以毫秒设置 Date 对象。 |
Date对象相关的字符串表示方法:
方法名 | 作用 |
---|---|
toSting() | 获取Date实例的字符串表示 |
toDateSting() | 获取Date的日期部分字符串表示 |
toTimeSting() | 获取Date的时间部分字符串表示 |
toLocaleString() | 据本地时间格式,把 Date 对象转换为字符串。 |
toLocaleDateString() | 根据本地时间格式,把 Date 对象的日期部分转换为字符串。 |
toLocaleTimeString() | 根据本地时间格式,把 Date 对象的时间部分转换为字符串。 |
valueOf() | 返回1970年1月1日午夜到指定日期的毫秒数 |
Date.now() | 返回1970年1月1日午夜到指定日期的毫秒数(HTML5中提供的方法,有兼容性问题) |
7.3 String对象
字符串的不可变
-
重新给字符串赋值,会重新在内存中开辟空间,这个特点就是字符串的不可变
-
由于字符串的不可变,在大量拼接字符串的时候会有效率问题
String对象方法
方法名 | 作用 |
---|---|
charAt(index) | 返回在指定位置的字符。 |
charCodeAt() | 返回在指定的位置的字符的 Unicode 编码。 |
concat([string1,string2…) | 连接字符串。 |
slice(start,end) | 提取字符串n到m之间的片断(不包括m位置的字符串),并在新的字符串中返回被提取的部分。 |
substring(star,end) | 提取字符串中两个指定的索引号之间的字符。大多数情况和上一个作用相同,当参数为负值时会有不同,但这种情况较少用,不做讨论,有兴趣的话自己测试或查下资料 |
substr(start,length) | 从起始索引号提取字符串中指定数目的字符。 |
split(separator,limit) | 把字符串分割为字符串数组。 |
indexOf(subString[,startIndex]) | 检索字符串,返回某个指定的字符串值在字符串中首次出现的位置。如果查找不到会返回 -1 |
astIndexOf(subString[,startIndex]) | 返回指定字符串在字符串最后出现的位置。 |
toLowerCase() | 把字符串转换为小写。 |
toUpperCase() | 把字符串转换为大写。 |
match() | 找到一个或多个正则表达式的匹配。该方法会返回一个数组,数组中包含了所符合条件的本。 |
replace(rgExp, replaceText) | 替换与正则表达式匹配的子串,并返回替换后的字符串,注意原字符串不会改变。 |
search(rgExp) | 回与正则表达式查找内容匹配的第一个子字符串的位置。(与indexOf相似) |
7.4 Math对象
Math对象不是构造函数,它具有数学常数和函数的属性和方法,都是以静态成员的方式提供。
Math对象并不像Date和String那样是对象的类,因此没有构造函数Math()。
方法名/属性名 | 作用 |
---|---|
Math.PI | 返回圆周率(约等于3.14159)。 |
Math.ceil(x) | 返回大于等于其数字参数的最小整数。 |
Math.floor(x) | 返回小于等于其数值参数的最大整数。 |
Math.round(x) | 把数四舍五入为最接近的整数。 |
Math.random() | 返回介于 0 和 1 之间的伪随机数。 注:产生的伪随机数介于 0 和 1 之间(含0,不含 1),返回值可能为0,但总是小于1。 |
Math.max(x,y) | 返回 x 和 y 中的最高值。 |
Math.min(x,y) | 返回 x 和 y 中的最低值。 |
Math.abs(x) | 返回x的绝对值。 |
7.5 全局对象
1、parseInt
- parseInt() 函数可以解析一个字符串,并返回一个整数。
2、parseFloat方法
-
parseFloat()函数可以解析一个字符串,并返回一个浮点数。
-
该函数指定字符串中的首个字符是否是数字。如果是,则对字符串进行解析,
直到到达数字的末端为止,然后以数字返回该数字,而不是作为字符串。
-
如果参数字符串的第一个字符不能被解析成为数字,则 parseFloat 返回 NaN。
3、isNaN()方法
-
isNaN(x):函数用于检查其参数是否是非数字值。
-
参数x是要检测的值,
如果x是特殊的非数字值NaN(或者能被转换为这样的值),返回的值就是true。
如果 x 是其他值,则返回 false。
-
isNaN()函数可用于判断其参数是否是NaN,该值表示一个非法的数字
如果把NaN与任何值(包括其自身)相比得到的结果均是false,
要判断某个值是否是NaN,不能使用 == 或 === 运算符。因此,isNaN() 函数是必需的。