banner
banner
banner
NEWS LETTER

JS-基础

Scroll down

JavaScript

负责页面中的的行为,运行在浏览器端的脚本语言。

输出语句

alert(“要输出的内容”);

  • 该语句会在浏览器窗口中弹出一个警告框

document.write(“要输出的内容”);

  • 该内容将会被写到 body 标签中,并在页面中显示

console.log(“要输出的内容”);

  • 该内容会被写到开发者工具的控制台中

基本语法

  • 单行注释 // …
  • 多行注释 /_ … _/
  • JS 中严格区分大小写
  • JS 中每一条语句以分号(;)结尾,只有单行内需要分割语句,这个分号才是必须的
  • JS 中会忽略多个空格和换行
  • JS 语句是按照自上向下的顺序一条一条执行的
  • 在 JS 中可以使用{}来为语句进行分组,同一个{}中的语句我们称为是一组语句,这一组语句我们也称为一个代码块

标识符

  • 在 JS 中所有的可以由我们自主命名的都可以称为是标识符
  • 例如:变量名、函数名、属性名都属于标识符
  • JS 底层保存标识符时实际上是采用的 Unicode 编码,所以理论上讲,所有的 utf-8 中含有的内容都可以作为标识符
  • 命名规则:
    1. 标识符中可以含有字母、数字、_、$
    2. 标识符不能以数字开头
    3. 标识符不能是 ES 中的关键字或保留字
    4. 标识符一般都采用驼峰命名法 — aBbbCcc

JS 的编写位置

  • 编写到外部 js 文件中,然后通过 script 标签引入(推荐)
    • 好处:可以复用多个页面
    • 坏处:不能在编写修改,但是可以使用内部 script 标签
    • <script type="text/javascript" src="文件路径"></script>
  • 编写到 script 标签内 — 写在页面底部
    • <script type="text/javascript"></script>
  • 写在超链接的 href 属性中,这样当点击超链接时,会执行 js 代码
    • <a href="javascript:alert('点击弹窗');">弹窗</a>
  • 编写到标签的 onclick 属性中,当我们点击按钮时,js 代码才会执行(不推荐)
    • <button onclick="alert("点击弹窗")"></button>

数据 | 内存 | 变量

数据

  • 存储于内存中代表特定信息的, 本质就是 0101 二进制
  • 具有可读和可传递的基本特性
  • 万物(一切)皆数据, 函数也是数据

内存

  • 内存条通电后产生的存储空间(临时的)
  • 产生和死亡: 内存条(集成电路板)==>通电==>产生一定容量的存储空间==>存储各种数据==>断电==>内存全部消失
  • 内存的空间是临时的, 而硬盘的空间是持久的
  • 一块内存包含 2 个数据
    • 内部存储的数据(一般数据/地址数据)
    • 内存地址值数据
  • 内存分类
    • 栈: 全局变量, 局部变量 (空间较小)
    • 堆: 对象 (空间较大)

变量

  • 值可以变化的量, 由变量名与变量值组成
  • 一个变量对应一块小内存, 变量名用来查找到内存, 变量值就是内存中保存的内容
  • 声明变量
    • 使用 var、const、 let 关键字声明
    • var a;
  • 为变量赋值: a = xxx;
  • 声明和赋值同时进行:var a = xx;

三者之间的关系

  • 内存是一个容器, 用来存储程序运行需要操作的数据
  • 变量是内存的标识, 我们通过变量找到对应的内存, 进而操作(读/写)内存中的数据

问题: JS 引擎如何管理内存?

  • 内存生命周期
    1. 分配需要的内存
    2. 使用分配到的内存
    3. 不需要时将其释放/归还
  • 释放内存
    • 为执行函数分配的栈空间内存: 函数执行完自动释放
    • 存储对象的堆空间内存: 当内存没有引用指向时, 对象成为垃圾对象, 垃圾回收器后面就会回收释放此内存

var & let & const

es6 之前创建变量只有 var,let/const 是 es6 后出来的

  • var 定义的变量,没有块的概念,可以跨块访问,不能跨函数
  • let 定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问
  • const 用来定义常量,使用时必须初始化(即赋值),只能块作用域里访问,且不能修改
  • var 定义的变量可以先使用,后声明,存在变量提升,let 必须先声明后使用
  • var 允许在相同作用域内重复声明同一个变量,let 和 const 不允许
  • 在全局上下文中,基于 var 声明的变量会和全局对象(window)有映射,而 let 不会
  • 会产生暂时性死区:检测一个未被声明的变量类型时,不会报错,会返回 undefined
  • let、const 会把当前所在的大括号作为一个全新的块级上下文

数据存储

可以用来保存字面量,而且变量的值是可以任意改变的

  • JS 中的变量都是保存到栈内存中的,
  • 基本数据类型的值直接在栈内存中存储,值与值之间是独立存在,修改一个变量不会影响其他的变量
  • 对象是保存到堆内存中的,每创建一个新的对象,就会在堆内存中开辟出一个新的空间,
  • 变量保存的是对象的内存地址(对象的引用),如果两个变量保存的是同一个对象引用,当一个通过一个变量修改属性时,另一个也会受到影响
  • 比较两个基本数据类型的值时,就是比较值
  • 比较两个引用数据类型时,它是比较对象的内存地址,如果两个对象是一样,但是地址不同,它也会返回 false

关于引用变量赋值问题

  • 2 个引用变量指向同一个对象, 通过一个引用变量修改对象内部数据, 另一个引用变量也看得见
  • 2 个引用变量指向同一个对象,让一个引用变量指向另一个对象, 另一个引用变量还是指向原来的对象

问题: 在 js 调用函数时传递变量参数时, 是值传递还是引用传递

  • 只有值传递, 没有引用传递, 传递的都是变量的值, 只是这个值可能是基本数据, 也可能是地址(引用)数据
  • 如果后一种看成是引用传递, 那就值传递和引用传递都可以有

转义字符

  • \":表示 “
  • \':表示 ‘
  • \n:表示换行
  • \t:制表符
  • \\:表示\

js 的数据类型

  • 七种基本类型,一种引用类型
  • Number、Boolean、String、undefined、null、Bigint(es2020 新增,范围比 Number 的大)、Symbol(ES6 新增)
  • Object对象(包括普通ObjectFunctionArrayDateRegExpMath)

Number 数值

  • 特殊的数字
    Infinity 正无穷
    -Infinity 负无穷
    NaN 非法数字(Not A Number)
  • 进制:
  • 如果需要表示16进制的数字,则需要以0x开头
  • 如果需要表示8进制的数字,则需要以0开头
  • 如果要要表示2进制的数字,则需要以0b开头,但是不是所有的浏览器都支持
    • 示例:像”070”这种字符串,有些浏览器会当成 8 进制解析,有些会当成 10 进制解析
  • 可以在parseInt()中传递一个第二个参数,来指定数字的进制
    • 示例:a = parseInt(a,10);

null 和 undefined

  • undefined 代表没有赋值
  • null 代表赋值了, 只是值为 null
  • 由于 undefined 衍生自 null,所以 null == undefined 会返回 true。
  • 但是 null === undefined 会返回 false。
  • null 的使用
    • var a = null // a 将指向一个对象, 但对象此时还没有确定
    • a = null // 让 a 指向不再使用的对象成为垃圾对象(垃圾回收机制 GC)

NaN

  • 与任何值都不相等,包括自身
  • 可以通过 isNaN()函数来判断一个值是否是 NaN
  • function isNaN(x){ return x! = x}
  • 机制:会先判断参数是不是 Number 类型,不是尝试转为 Number,之后再去判断是不是 NaN

Unicode 编码

  • \u四位编码:在字符串中使用的 Unicode 编码
  • &#编码:在网页中使用的 Unicode 编码,这里的编码需要的是 10 进制
    • 示例:<h1 style="font-size: 200px;">&#9760;</h1>

typeof — 类型检测方案

区分数据类型,并返回 number、 string、 boolean、undefined、object、function、symbol

  • 对于基本数据类型,除null都可以正确判断
  • 对于引用类型除function外,都会返回object
  • typeof 返回值是 string,即双层typeof返回的类型是string
  • typeof未定义的变量,返回"undefined"
  • typeof(null) —> object
  • typeof(NaN) —> number
  • typeof(Infinity) —> number

instanceof — 类型检测方案

判断对象的原型链上是否存在构造函数的原型。只能判断引用类型。检查一个对象是否是一个类的实例

  • 语法:A instanceof B,常用来判断 A 是否为 B 的实例,如果是,则返回 true,否则返回 false,
  • 如果 B 函数的显式原型对象在 A 对象的原型链上, 返回 true, 否则返回 false
  • arr instanceof Array ,可以判断数组类型,但不推荐,因为如果网页存在多个 iframe,便会存在多个 Array 构造函数,此时判断会存在问题
  • 所有的对象都是 Object 的后代,所以任何对象和 Object 左 instanceof 检查时都会返回 true
  • Number、Boolean、String 基本类型不能判断

Object.prototype.toString.call([value]) — 类型检测方案

可以精准判断数据类型,与 Array.isArray 结合使用可以判断数组和对象,此方式兼容性最好

1
2
3
4
5
6
7
8
if (!Array.isArray) {
Array.isArray = function (o) {
return (
typeof o === 'object' &&
Object.prototype.toString.call(o) === '[object Array]'
)
}
}

类型转换

在 js 中,只有三种类型转换

转换为 Number 类型:Number()/parseFloat()/parseInt()

  • 显式/强制:直接使用 Number()/parseFloat()/parseInt()
  • 隐式:比较操作(<,>,<=,>=)、按位操作(|,&,^,~)、算术操作(+,-,*,/,%)、一元+-操作
  • Number 类型使用 toString(整数)可以将数字转为指定的进制,默认 10 进制
  • parseFloat(): 把一个字符串转换为一个浮点数
  • parseInt(): 把一个字符串转换为一个整数,将一个字符串中的有效的整数内容取出来
    1
    2
    3
    4
    ['1','2','3'].map(parseInt)相当于执行了以下三次过程:
    parseInt('1', 0, ['1','2','3']): radix 为 0 时,默认取 10,最后返回 1
    parseInt('2', 1, ['1','2','3']): radix 取值为 2~36,返回 NaN
    parseInt('3', 2, ['1','2','3']): radix 取值为 2,二进制只包括 01,返回 NaN
  • 非 String使用 parseInt()或 parseFloat(),会先将其转换为 String 然后在操作
  • 字符串 –> 数字
    类型 结果
    undefined NaN
    null +0
    Boolean true:1,false:+0
    Number 返回对应的值
    String 空字符串返回 0,出现任何一个非有效数字返回 NaN,其他的直接转换为对应的值
    Object 先执行 ToPrimitive 方法,再执行 Number 类型转换

转换为 String 类型:String()/toString()

  • 显式/强制:直接使用 String()/toString()
  • 隐式:+ 运算符有一侧操作数为 string 类型
  • null 或 undefined 调用 String()方法,返回字符串格式是它们本身
  • null 或 undefined 使用 toString()会报错

转化为 Boolean 类型:Boolean()

  • 显式/强制:直接使用 Boolean()
  • 隐式:通过 !! 或 !
  • 除 0,-0,null,NaN,undefined,或空字符串(“”)为 false 外,其余全为 true

==隐式转换规则

  • 类型相同的比较
    • 类型是 undefined 或 null, 返回 true
      • 如:null == null // true
      • 如:undefined == undefined // true
    • 如果一个是+0,另一个是-0,返回 true
      • 如:+0 == -0 //true
    • 如果类型是对象,二者引用同一个对象,返回 true,否则返回 false
      • 如:{} == {} // false
  • null 和 undefined 比较,仅当它们之间比较返回 true
    • 如:null == undefined // true
  • NaN 比较,NaN 与任何之后比较都返回 false,包括自己
    • 如:NaN == NaN // false
  • 字符串与数字比较,先将字符串转换为数字在比较
  • 布尔值与非布尔值比较:先将布尔值转换为数字在比较
  • 对象与原始类型比较,将对象通过ToPrimitive转换为原始类型对应的类型在比较
    • 如:{} == 1 // false
  • ! 的优先级高,如遇到[] == ![], 先进行非运算,
    • 又因为任何对象转换成布尔值都得到true,先转布尔在非运算
    • 即 ![] == false, 根据==隐式转换规则,对象与原始类型转换,两边先转为数字在比较,
    • 即 ![] ==> false ==> 0
    • [] 经过 ToPrimitive 方法 转换为’ ‘,
    • 所以[] == ![] 变成 ‘ ‘ == 0
    • 然后根据字符串与数字比较,先将字符串转为数字在比较,’’ 的布尔值为 0
    • 即 0 == 0 ,为 true
  • 其他的
    • {} == !{} // !{}->false->0 {}->”[object Object]”->NaN
    • {} == true
    • [] == [] // false 比较引用地址
    • {} == [] // 报错
    • {} + {} // “[object Object][object Object]”
    • {} + [] // 0 ,{}被当做一个块,并非{}转NaN,相当于执行 ({},+[]),返回值为小括号最后面的表达式的返回值
    • {q:1} + [] // 0
    • var a = {q:1};a + [] // “[object Object]”

toString 和 valueOf 方法有什么区别

都属于 Object 对象,是为了解决 JavaScript 值运算与显示的问题。

  • js 对象的键必须是字符串
  • toString(): 返回当前对象的字符串形式
  • valueOf() : 返回该对象的原始值
    类型 valueOf toString
    Array[1,2,3] 数组本身[1,2,3] “1,2,3”
    Object 对象本身 [object Object]
    Boolean 类型 Boolean 值 “true” 或”false”
    Function 函数本身 function fnName(){code}
    Number 数值 数值的字符串形式
    Date 毫米格式时间戳 GMT 格式时间字符串
  • 隐式转换会自动调用 toString 和 valueOf
    • 强制转化为字符串类型时,优先调用 toString
    • 强制转化为数值类型时,优先调用 valueOf
    • 使用运算符操作符情况下,valueOf 优先级高于 toString
    • 对象类型转换为原始值回调用内置的[ToPrimitive]函数
      • ToPrimitive 方法接受两个参数,一个是输入的值 value,一个是期望转换的类型 Type
        1. 如果未传入 PreferredType 参数,让 hint 等于’default’,后面会将 hint 修改为”number”
        2. 如果 value 是 基本类型,直接返回对应的类型的值
        3. 否则,调用 valueOf 方法,如果得到原始值,则返回
        4. 否则,调用 toString 方法,如果得到原始值,则返回
        5. 否则,报错
      • OrdinaryToPrimitive(input,hint)
        1. 如果 hint 是 ‘string’,那么就将 methodNames 设置为 toString、valueOf
        2. 如果 hint 是 ‘number’,那么就将 methodNames 设置为 valueOf、toString
1
2
3
4
5
- 设变量a={x:100},obj={},然后设obj[a] = 100 ,则此时obj[a]为多少?
- 解:由于js对象的键必须为字符串,所以先将变量a转换为字符串,即a = "{x:100}"
然后因为强制转化为字符串类型时,优先调用toString,通过上方表格可知,obj[a]为[object Object]
- {} + 1 :js引擎回解析成1个代码块和11,最终结果为1
- 1 + {} :先将{}调用ToPrimitive转为'[object Object]',然后跟1拼串,最终结果1[object Object]

运算符

逻辑运算符

  • !!: 将变量化为布尔
  • !:取反,对非 boolean 类型的元素,则会将其转boolean类型再取反
  • &&:只有两个值都为 true 时,才会返回 true,如果第一个值为 false,则不会看第二个值
    • 对于非布尔值进行与或运算时,会先将其转换为布尔值,然后再运算,并且返回原值
    • 如果第一个值为true,则必然返回第二个值
    • 如果第一个值为false,则直接返回第一个值
    • 如果两个值都为true,则返回后边的
  • ||:两个值中只要有一个 true,就返回 true,如果第一个值为 true,则不会检查第二个值
    • 对于非布尔值进行与或运算时,会先将其转换为布尔值,然后再运算,并且返回原值
    • 如果第一个值为true,则直接返回第一个值
    • 如果第一个值为false,则返回第二个值
    • 如果两个值中有false,则返回靠前的false

赋值运算符

  • =:赋值
  • +=:a += 5 相当于 a = a+5
  • -=:a -= 5 相当于 a = a-5
  • *=:a = 5 相当于 a = a5
  • /=:a /= 5 相当于 a = a/5
  • %=:a %= 5 相当于 a = a%5
  • n++,n--:先自增,自减,并且赋值时,把自增、自减前的值的赋值,即得到的结果是变量的原值
  • ++n,--n:先自增,自减,并且把变化后的值赋值给变量,即得到的结果是变量的新值
  • 示例:
1
2
3
4
const n1 = 10
const n2 = 10
var n = n1++ //n1 = 11 n1++ = 10 n = 10
var m = ++n2 //n2 = 11 ++n1 = 11 n = 11

相等运算符

  • ==:等于,值相等返回 true,如果值的类型不同,则会自动进行类型转换,将其转换为相同的类型,然后在比较
  • !=:不等于,两个值是否不相等,不相等返回 true,也会对变量进行自动的类型转换,然后在比较
  • ===:绝对等于,类型也相等,不会做自动的类型转换
  • !==:不全等,不会做自动的类型转换,如果两个值的类型不同,直接返回 true

算数运算符

  • +、-、*、/:加减乘除,任何值做-、/、*运算时都会自动转换为 Number
  • %:算数运算符,取模运算(取余数)

关系运算符

  • >、>=、<、<=
    • 对于非数值进行比较时,会将其换为数字然后在比较
    • 如果符号两侧的值字符串时,会分别一位一位比较字符串中字符的Unicode编码
    • 注:在比较两个字符串型的数字时,一定要转型

三元运算符(条件运算符)

  • 语法:条件表达式?语句1:语句2;
  • 执行的流程:
    • 条件运算符在执行时,首先对条件表达式进行求值,
    • 为 true,则执行语句 1,并返回执行结果,为 false,则执行语句 2,并返回执行结果
    • 如果条件的表达式的求值结果是一个非布尔值,会将其转换为布尔值然后在运算

一元运算符

  • +、-正负号,只需要一个操作数
    • 对于非 Number 类型的值,会先转换为 Number,然后在运算
    • + 变量化为Number类型
    • 任何值和字符串相加都会转换为字符串,叫做拼串操作

流程控制语句

条件判断语句

  • 语法一:if(条件表达式){为 true 语句…}
  • 语法二:if(条件表达式){为 true 语句…}else{为 false 语句…}
  • 语法三:if(条件表达式){语句…}else if(条件表达式){语句…}else{语句…}

条件分支语句 switch

  • 语法:
1
2
3
4
5
6
7
switch(条件表达式){
case 表达式:
语句...
break;
default
break;
}
  • 执行流程
    • 依次将 case 后的表达式的值和 switch 后的条件表达式的值进行全等比较,如果为 true,则从当前 case 处开始执行代码。
    • 为 false,则继续向下比较,知道所有结果都为 false,只执行 default 后的语句

循环语句

  • for循环
    • 语法:for(① 初始化表达式;② 条件表达式;④ 更新表达式){ 语句… }
    • 执行流程:
      • 执行初始化表达式,初始化变量(初始化表达式只会执行一次)
      • 执行条件表达式,判断是否执行循环。为 true,则执行循环,为 false,终止循环
      • 执行更新表达式,更新表达式执行完毕继续重复上一步
    • 注:for 循环中的三个部分都可以省略,也可以写在外部,for(;;){}死循环
    • 示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
打印2-1000质数
for(var i=2 ; i<=1000; i++){
var flag = true;
for(var j=2 ; j<=Math.sqrt(i) ; j++){
if(i%j == 0){
//如果进入判断则证明i不是质数,修改flag值为false
flag = false;
break;
}
}
//如果是质数,则打印i的值
if(flag){
document.write(i+' ')
}
}
打印九九乘法表
//创建外层循环,用来控制乘法表的高度
for(var i=1 ; i<=9 ; i++ ){
// 创建一个内层循环来控制图形的宽度
for(var j=1 ; j<=i ; j++){
document.write("<span>"+j+"*"+i+"="+i*j+"</span>");
}
document.write("<br />"); //输出一个换行
}
  • while循环
    • 语法:while(条件表达式){ 语句… }
    • 执行流程
      • 先对条件表达式进行求值判断,
      • 如果值为 true,则执行循环体,
      • 循环体执行完毕以后,继续对表达式进行判断,以此类推
      • 如果值为 false,则终止循环
  • do…while循环
    • 语法:do{ 语句… }while(条件表达式)
    • 执行流程:
      • 先执行循环体,
      • 循环体执行完毕以后,在对 while 后的条件表达式进行判断,
      • 如果结果为 true,则继续执行循环体,执行完毕继续判断以此类推 -如果结果为 false,则终止循环
  • do…while循环和while循环区别
    • while 是先判断后执行,
    • 而 do…while 会先执行后判断,
    • do…while 可以保证循环体至少执行一次,而 while 不能
      var n = 1;
  • 将条件表达式写死为 true 的循环,叫做死循环,可以使用 break,来终止循环

函数 function

函数也是一个对象,函数中可以封装一些功能,在需要时可以执行这些功能

创建一个函数对象

  • 方法一:使用构造函数(少用)
    • 语法:const fun = new Function(语句…);
  • 方法二:使用函数声明
    • 语法:function 函数名([形参 1,形参 2…形参 N]){ 语句… }
  • 方法三: 使用函数表达式
    • 语法: const 函数名 = function([形参 1,形参 2…形参 N]){ 语句… }

调用方法:

  • 函数对象([实参 1,实参 2])
  • new 函数对象()
  • 对象.函数对象()
  • 函数对象.call/apply(obj)

形参与实参:

  • 实参:
    • 在调用函数时,可以在()中指定,实参将会赋值给函数中对应的形参
    • 调用函数时解析器不会检查实参的类型和数量,可以传递任意数据类型的值
    • 多余实参不会被赋值,如果实参的数量少于形参的数量,则没有对应实参的形参将是 undefined
  • 形参:
    • 定义函数时,可以在()中定义一个或多个形参,形参之间使用,隔开
    • 定义形参就相当于在函数内声明了对应的变量但是并不赋值,形参会在调用时才赋值。

构造函数:

  • 创建一个构造函数:与普通函数一样,但首字母要大写
  • 调用方式:使用 new 关键字来调用
  • 构造函数是专门用来创建对象的函数
  • 一个构造函数我们也可以称为一个类
  • 通过一个构造函数创建的对象,我们称该对象时这个构造函数的实例
  • 通过同一个构造函数创建的对象,我们称为一类对象
  • 构造函数就是一个普通的函数,只是他的调用方式不同,
    • 如果直接调用,它就是一个普通函数
    • 如果使用 new 来调用,则它就是一个构造函数
  • 执行流程:
    1. 立刻创建一个新的对象
    2. 将新建的对象设置为函数中 this,在构造函数中可以使用 this 来引用新建的对象
    3. 逐行执行函数中的代码
    4. 将新建的对象作为返回值返回

作用域

  • 定义:变量与函数的可访问范围,由当前环境与上层环境的一系列变量对象组成。
  • 全局作用域:

    • 直接编写在 script 标签中的 JS 代码,都在全局作用域
    • 全局作用域在页面打开时创建,在页面关闭时销毁
    • 在全局作用域中有一个全局对象 window,
    • 创建的变量都会作为 window 对象的属性保存
    • 创建的函数都会作为 window 对象的方法保存
    • 全局作用域中的变量都是全局变量,在页面的任意的部分都可以访问的到
    • 在函数作用域中也可以访问到全局作用域的变量。
    • 尽量不要在全局中创建变量
  • 函数作用域:函数执行时创建的作用域

    • 函数作用域在函数执行时创建,在函数执行结束时销毁。
    • 每调用一次函数就会创建一个新的函数作用域,他们之间是互相独立的
    • 在函数作用域中可以访问到全局作用域的变量,反过来不行
    • 在函数中要访问全局变量可以使用 window 对象
  • 作用:隔离变量,不同作用域同名变量不会有冲突。

作用域链

  • 定义:调用某个函数或属性时,先在当前作用域寻找,如果找不到的情况下去父级寻找,如果父级找不到继续向上级寻找,直到找到全局作用域为止,如果全局作用域中依然没有找到,则会报错 ReferenceError,这就是链式查找的过程

声明提前

变量的声明提前

  • 使用 var 关键字声明的变量,会在所有的代码执行之前被声明(但是不会赋值)
  • 但是如果声明变量时不使用 var 关键字,则变量不会被声明提前
  • 在函数作用域中,也具有以上特性
  • 在函数作用域中,不使用关键字声明的变量都会成为全局变量

函数的声明提前

  • 在全局作用域中, 使用函数声明形式创建的函数 function 函数(){},会在所有的代码执行之前就被创建,所以可以在函数声明前来调用函数
  • 在全局作用域中,使用函数表达式创建的函数 var fun = function(){},不会被声明提前,所以不能在声明前调用
  • 在函数作用域中,使用函数声明创建的函数,会在所有的函数中的代码执行之前就被创建好了。

函数的方法

  • call() 和 apply()
    • 这两个方法都是函数对象的方法,需要通过函数对象来调用
    • 通过两个方法可以直接调用函数,并且可以通过第一个实参(对象)来指定函数执行中 this
    • call()方法可以将实参在对象之后依次传递
    • apply()方法需要将实参封装到一个数组统一传递
  • arguments(封装实参的对象)
    • arguments 和 this 类似,都是函数中的隐含的参数
    • arguments 是一个类数组元素,它可以通过索引来操作数据,获取长度
    • 在调用函数时,我们所传递的实参都会在 arguments 中保存
    • arguments.length 可以用来获取实参的长度
    • arguments 中有一个属性 callee 表示当前执行的函数对象
      • function fun(a,b) { console.log(arguments.callee == fun) } // true
    • 即使不定义形参,也可以通过 arguments 来使用实参
      • arguments[0] 表示第一个实参
      • arguments[1] 表示第二个实参

this(函数的上下文对象)

  • 解析器在每次调用函数都会向函数内部传递进一个隐含的参数,这个隐含的参数就是 this
  • this 指向的是一个对象,这个对象我们称为函数执行的上下文对象
  • 使用 this 来引用上下文对象,根据函数的调用形式不同,this 的值也不同
  • 以函数的形式调用时,this是window — xxx(),指向 window
  • 以方法的形式调用时,谁调用方法this就是谁 — obj.xxx(), 指向 obj
  • 以构造函数的形式调用时,this就是新创建的那个对象
  • 通过 call/apply 指定谁调用: xxx.call(obj),指向 obj
  • 在全局作用域中 this 代表 window
  • 示例
1
2
3
4
5
6
7
8
9
10
function Person(name, age, gender) {
// 定义了形参,创建构造函数
this.name = name
this.age = age
this.gender = gender
this.sayName = function () {
alert(this.name)
}
}
var per = new Person('孙悟空', 18, '男') // this执行per,并传了实参

(IIFE)立即执行函数:

  • 全称: Immediately-Invoked Function Expression 立即调用函数表达式
  • 别名: 匿名函数自调用
  • 定义:函数定义完,立即被调用,往往只会执行一次
  • 语法:(function(){ alert(“我是一个匿名函数~~~”); })();
  • 作用
    • 隐藏内部实现
    • 不污染外部命名空间

回调函数

  • 定义:定义了该函数,没有直接执行,需要按下或者在一定时候才会执行的函数
  • 常见的回调函数
    • DOM 事件函数
    • 定时器函数
    • ajax 回调函数
    • 生命周期回调函数
1
2
3
4
5
6
7
8
9
// DOM事件函数
var btn = document.getElementById('btn')
btn.onclick = function () {
alert(this.innerHTML)
}
// 定时器函数
setInterval(function () {
// alert('到点啦!')
}, 20000)

对象

对象的分类:

  • 内建对象 — 由 ES 标准中定义的对象,在任何的 ES 的实现中都可以使用
    • 比如:Math String Number Boolean Function Object….
  • 宿主对象 — 由 JS 的运行环境提供的对象,目前来讲主要指由浏览器提供的对象
    • 比如 BOM DOM
  • 自定义对象 — 由开发人员自己创建的对象

in 运算符

  • 定义:检查一个对象中是否含有指定的属性,有则返回 true,没有则返回 false
  • 语法:”属性名” in 对象

使用 new 关键字创建一个对象

  • 语法:使用 new 关键字调用的函数,是构造函数 constructor,var obj = new Object();
  • 向对象中添加属性:对象.属性名 = 属性值(可以是任意类型,也可以是个函数)
    • 特殊属性名的添加方式:对象[“属性名”] = 属性值
  • 读取对象中的属性:对象.属性名,如果读取对象中没有的属性,返回 undefined
    • 特殊属性名的读取方式:对象[“属性名”]
  • 修改对象的属性值:对象.属性名 = 新值
  • 删除对象的属性:delete 对象.属性名
  • 调用方法:对象.函数对象(); // 如果一个函数作为一个对象的属性值保存,那么我们称这个函数是这个对象的方法

使用对象字面量来创建一个对象

  • 语法:const 对象 = {属性名:属性值,属性名:属性值….}; // 可以在创建对象时,直接指定对象中的属性,也可以为空
  • 属性名可以加引号也可以不加,如果要使用一些特殊的名字,则必须加引号
  • 属性名和属性值是一组一组的名值对结构,名和值之间使用:连接,多个名值对之间使用,隔开
  • 示例
1
2
3
4
5
6
const obj = {
name: '孙悟空',
age: 18,
gender: '男',
address: '花果山',
}

使用工厂方法传建对象

  • 优点:可以批量创建
  • 缺点:创建的对象都是 Object 这个类型,无法区分出多种不同类型的对象
  • 示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function createPerson(name, age, gender) {
//创建一个新的对象
var obj = new Object()
//向对象中添加属性
obj.name = name
obj.age = age
obj.gender = gender
obj.sayName = function () {
alert(this.name)
}
//将新的对象返回
return obj
}
var obj2 = createPerson('猪八戒', 28, '男')
var obj3 = createPerson('蜘蛛精', 18, '女')

枚举对象中的属性使用 for … in 语句

  • 语法:for(var 变量 in 对象){}
  • for…in 语句 对象中有几个属性,循环体就会执行几次
  • 每次执行时,会将对象中的一个属性的名字赋值给变量
  • 示例
1
2
3
4
for (var n in obj) {
console.log('属性名:' + n)
console.log('属性值:' + obj[n])
}

break | continue | return

break 关键字 — 会立即终止离他最近的那个循环语句

  • 可以用来退出 switch 或循环语句,
  • 不能在 if 语句中使用 break 和 continue

label — 标识当前的循环

  • 语法:label:循环语句
  • 使用 break 语句时,可以在 break 后跟着一个 label,这样 break 将会结束指定的循环
  • 示例
1
2
3
4
5
6
7
8
// 给循环标识了一个label
outer: for (var i = 0; i < 5; i++) {
console.log('@外层循环' + i)
for (var j = 0; j < 5; j++) {
break outer // 退出时,结束outer这个循环
console.log('内层循环:' + j)
}
}

continue 关键字 — 用来跳过当次循环

  • 同样 continue 也是默认只会对离他最近的循环循环起作用

return — 可以结束整个函数

  • 语法:return 值(任意类型的值,不写相当于 undefined)
  • 可以使用 return 来设置函数的返回值,值将会作为函数的执行结果返回
  • 在 return 后的语句都不会执行
其他文章
cover
JS-数组
  • 24/10/31
  • 11:05
  • JavaScript
cover
案例-时间轴特效
  • 24/10/30
  • 15:29
  • CSS&HTML
目录导航 置顶
  1. 1. JavaScript
    1. 1.1. 输出语句
      1. 1.1.1. alert(“要输出的内容”);
      2. 1.1.2. document.write(“要输出的内容”);
      3. 1.1.3. console.log(“要输出的内容”);
    2. 1.2. 基本语法
    3. 1.3. 标识符
    4. 1.4. JS 的编写位置
    5. 1.5. 数据 | 内存 | 变量
      1. 1.5.1. 数据
      2. 1.5.2. 内存
      3. 1.5.3. 变量
      4. 1.5.4. 三者之间的关系
      5. 1.5.5. 问题: JS 引擎如何管理内存?
    6. 1.6. var & let & const
    7. 1.7. 数据存储
      1. 1.7.1. 关于引用变量赋值问题
      2. 1.7.2. 问题: 在 js 调用函数时传递变量参数时, 是值传递还是引用传递
    8. 1.8. 转义字符
    9. 1.9. js 的数据类型
      1. 1.9.1. Number 数值
      2. 1.9.2. null 和 undefined
      3. 1.9.3. NaN
      4. 1.9.4. Unicode 编码
    10. 1.10. typeof — 类型检测方案
    11. 1.11. instanceof — 类型检测方案
    12. 1.12. Object.prototype.toString.call([value]) — 类型检测方案
    13. 1.13. 类型转换
      1. 1.13.1. 转换为 Number 类型:Number()/parseFloat()/parseInt()
      2. 1.13.2. 转换为 String 类型:String()/toString()
      3. 1.13.3. 转化为 Boolean 类型:Boolean()
      4. 1.13.4. ==隐式转换规则
    14. 1.14. toString 和 valueOf 方法有什么区别
    15. 1.15. 运算符
      1. 1.15.1. 逻辑运算符
      2. 1.15.2. 赋值运算符
      3. 1.15.3. 相等运算符
      4. 1.15.4. 算数运算符
      5. 1.15.5. 关系运算符
      6. 1.15.6. 三元运算符(条件运算符)
      7. 1.15.7. 一元运算符
    16. 1.16. 流程控制语句
      1. 1.16.1. 条件判断语句
      2. 1.16.2. 条件分支语句 switch
      3. 1.16.3. 循环语句
    17. 1.17. 函数 function
      1. 1.17.1. 创建一个函数对象
      2. 1.17.2. 调用方法:
      3. 1.17.3. 形参与实参:
      4. 1.17.4. 构造函数:
      5. 1.17.5. 作用域
      6. 1.17.6. 全局作用域:
      7. 1.17.7. 函数作用域:函数执行时创建的作用域
      8. 1.17.8. 作用域链
    18. 1.18. 声明提前
      1. 1.18.1. 变量的声明提前
      2. 1.18.2. 函数的声明提前
      3. 1.18.3. 函数的方法
      4. 1.18.4. this(函数的上下文对象)
      5. 1.18.5. (IIFE)立即执行函数:
      6. 1.18.6. 回调函数
    19. 1.19. 对象
      1. 1.19.1. 对象的分类:
      2. 1.19.2. in 运算符
      3. 1.19.3. 使用 new 关键字创建一个对象
      4. 1.19.4. 使用对象字面量来创建一个对象
      5. 1.19.5. 使用工厂方法传建对象
      6. 1.19.6. 枚举对象中的属性使用 for … in 语句
    20. 1.20. break | continue | return
      1. 1.20.1. break 关键字 — 会立即终止离他最近的那个循环语句
      2. 1.20.2. label — 标识当前的循环
      3. 1.20.3. continue 关键字 — 用来跳过当次循环
      4. 1.20.4. return — 可以结束整个函数
请输入关键词进行搜索