五十二、JavaScript——函数简介
一、函数
- 函数(Function)
- 函数也是一个对象
- 它具有其他对象所有的功能
- 函数中可以储存代码,且可以在需要时调用这些代码
语法:
function 函数名(){
语句。。。
}
- 调用函数
- 调用函数就是执行函数中存储的代码
- 语法:
函数对象()
- 检查函数对象
- 使用(typeof 函数名)
- 注意: 函数名不要加括号 :(typeof fn)即可
- 函数创建
语法:
function 函数名(){
语句。。。
}
- 调用函数
- 调用函数就是执行函数中存储的代码
- 语法:
函数对象()
- 检查函数对象
- 使用(typeof 函数名)
- 注意: 函数名不要加括号 :(typeof fn)即可
<script>
/*
函数(Function)
- 函数也是一个对象
- 它具有其他对象所有的功能
- 函数中可以储存代码,且可以在需要时调用这些代码
语法:
function 函数名(){
语句。。。
}
调用函数
- 调用函数就是执行函数中存储的代码
- 语法:
函数对象()
检查函数对象
- 使用(typeof 函数名)
- 注意: 函数名不要加括号 :(typeof fn)即可
*/
//创建一个函数对象
function fn(){
//语句
console.log("你好!")
}
// console.log(fn)
fn()
fn()
console.log(typeof fn)
</script>
五十三、JavaScript——函数的创建方式
一、函数的创建方式
- 函数的定义方式
1.函数声明
function 函数名([参数]){
语句。。。
}
2. 函数表达式
const 变量 = function(){
语句。。。
}
3. 箭头函数
() => {
语句。。。
}
- 只有一个语句的时候,大括号可以省略不写
<script>
/*
函数的定义方式
1.函数声明
function 函数名([参数]){
语句。。。
}
2. 函数表达式
const 变量 = function(){
语句。。。
}
3. 箭头函数
() => {
语句。。。
}
- 只有一个语句的时候,大括号可以省略不写
*/
//函数声明
function fn(){
//语句
console.log("函数声明定义的函数")
}
fn()
console.log("函数声明中函数的类型"+typeof fn)
//函数声明
const fn2 = function fn(){
//语句
console.log("函数表达式")
}
fn2()
console.log("函数表达式中函数的类型"+typeof fn2)
const fn3 = () => {
console.log("箭头函数")
}
fn3()
console.log("箭头中函数的类型"+typeof fn3)
//只有一个语句的时候,大括号可以省略不写
const fn4 = () => console.log("只有一条语句时大括号可以省略")
fn4()
console.log("箭头中函数的类型"+typeof fn4)
</script>
五十四、JavaScript——参数简介
一、参数简介
- 参数
- 在定义函数时,可以在函数中执行数量不等的形式参数(形参)
- 在函数中定义参数,就相当于在函数内部声明了对应变量但没有赋值
- 实际参数
- 在调用函数时,可以在函数的()中传递数量不等的实参
- 实参就会赋值给对应的形参
- 参数
1. 如果实参和形参数量相同,则对应的实参赋值给对应的形参
2. 如果实参多于形参,则多余的实参不会使用
3. 如果形参多于实参,则多余的形参为undefinded
- 参数类型
- JS中不会检查参数的类型,可以传递任何类型的值作为参数
1.函数声明
function 函数名([参数]){
语句。。。
}
2. 函数表达式
const 变量 = function([参数]){
语句。。。
}
3. 箭头函数
([参数]) => {
语句。。。
}
- 只有一个语句的时候,大括号可以省略不写
<script>
/*
定义一个可以求任意两个数和的函数
*/
// function sum(){
// console.log(1+1)
// }
// sum()
// const sum2 = function(){
// console.log(1+1)
// }
// sum2()
// const su3 = () => console.log(1+1)
// sun3()
/*
参数
- 在定义函数时,可以在函数中执行数量不等的形式参数(形参)
- 在函数中定义参数,就相当于在函数内部声明了对应变量但没有赋值
实际参数
- 在调用函数时,可以在函数的()中传递数量不等的实参
- 实参就会赋值给对应的形参
- 参数
1. 如果实参和形参数量相同,则对应的实参赋值给对应的形参
2. 如果实参多于形参,则多余的实参不会使用
3. 如果形参多于实参,则多余的形参为undefinded
- 参数类型
- JS中不会检查参数的类型,可以传递任何类型的值作为参数
1.函数声明
function 函数名([参数]){
语句。。。
}
2. 函数表达式
const 变量 = function([参数]){
语句。。。
}
3. 箭头函数
([参数]) => {
语句。。。
}
- 只有一个语句的时候,大括号可以省略不写
*/
//定义函数传入形参
function fn(a,b){
console.log(a + b)
}
//调用函数传入实参
fn(1,10)
//可以传递任何类型的参数
fn(true,"张三")
</script>
五十五、JavaScript——箭头函数的参数和默认参数
一、箭头函数的参数和默认参数
当箭头函数中只有一个参数时,可以省略()
定义参数参数时,可以为参数指定默认值,有实参传实参, 没实参传默认值
<script>
//
const fn = (a, b) =>{
console.log("a="+a);
console.log("b="+b);
}
// 当箭头函数中只有一个参数时,可以省略()
const fn2 = a => {
console.log("a="+a)
}
fn2(123)
// 定义参数参数时,可以为参数指定默认值
// 有实参传实参, 没实参传默认值
const fn3 = (a=10,b=29,c=22) => {
console.log("a="+a)
console.log("b="+b)
console.log("c="+c)
}
//只传2个实参,第三个会使用默认值
fn3(1,2)
</script>
五十六、JavaScript——使用对象作为参数
一、对象作为参数传递
- 对象可以作为参数传递
<script>
function fn(a){
console.log("a=",a)
console.log(a.name) //打印 "张三"
}
// 对象可以作为参数传递
let obj = {name:"张三"}
fn(obj) // 打印 a= {name: '张三'}
</script>
- 修改对象时,如果有其他变量指向该对象,则所有指向该对象的而变量都会收到影响
- a.name = "李四“
<script>
function fn(a){
a.name = "李四" // 修改对象时,如果有其他变量指向该对象,则所有指向该对象的而变量都会收到影响
console.log(a.name) //打印 "李四"
}
// 对象可以作为参数传递
let obj = {name:"张三"}
fn(obj)
console.log(obj)
</script>
- 修改变量时,只会影响当前变量,开辟了一个新的空间,
- a = { }
<script>
function fn(a){
a = {} //修改变量时,只会影响当前变量,开辟了一个新的空间,
a.name = "李四" // 修改对象时,如果有其他变量指向该对象,则所有指向该对象的而变量都会收到影响
console.log(a.name) //打印 "李四"
}
// 对象可以作为参数传递
let obj = {name:"张三"}
fn(obj)
console.log(obj) //打印张三
</script>
- 有默认值时先每次调用时会重新创建默认值,创建新的对象,
- 两次调用并不是同一个对象,第二次调用相当于又内存中又新开辟了一个空间来存储对象
function fn(a = {name:"张三"}) 默认值 张三
<script>
function fn(a = {name:"张三"}){
console.log("a= ",a)
a.name = "李四" // 修改对象时,如果有其他变量指向该对象,则所有指向该对象的而变量都会收到影响
console.log("a= ",a) //打印 "李四"
}
//两次调用
fn()
fn()
// 传递实参时,传递的并不是变量本身,而是变量中存储的值
</script>
- function fn(a = fun)
- a 和 fun 指向同一个 对象,如果对象的值被修改了,那么影响就会一直持续下去,导致后面指向该对象的变量的值全部被修改
<script>
let fun = {name:"张三"}
// 每次调用共用一个对象
function fn(a = fun){
console.log("a= ",a)
a.name = "李四"
console.log("a= ",a)
}
//两次调用
fn()
fn()
// 传递实参时,传递的并不是变量本身,而是变量中存储的值
</script>
五十七、JavaScript——函数作为参数
一、函数作为参数
在JS中,函数也是一个对象(一等函数)
- 别的对象能做的事,函数也可以
<script>
function fn(a){
console.log("a=",a)
}
/*
在JS中,函数也是一个对象(一等函数)
- 别的对象能做的事,函数也可以
*/
function fn2(){
console.log("我是fn2")
}
//把fn2函数作为参数,传入函数中
fn(fn2)
fn(() =>console.log("我是箭头函数"))
</script>
五十八、JavaScript——函数的返回值
一、函数的返回值
在函数中,可以通过return关键字来指定函数的返回结果
返回值就是函数的执行结果,函数调用完完毕返回值便会作为结果返回
任何值都可以作为返回值使用(包括对象和函数之类)
如果return后不跟任何值,则相当于返回undefined
<script>
// function sum(a,b){
// console.log(a + b)
// //计算完成之后,将计算的结果返回而不是直接打印
// }
// sum(123,111)
let sum = ""
function fu(a,b){
/*
在函数中,可以通过return关键字来指定函数的返回结果
返回值就是函数的执行结果,函数调用完完毕返回值便会作为结果返回\
任何值都可以作为返回值使用(包括对象和函数之类)
如果return后不跟任何值,则相当于返回undefined
*/
sum = a +b
return sum
}
fu(111,222)
console.log("sum="+sum)
</script>
五十九、JavaScript——箭头函数的返回值
一、箭头函数的返回值
箭头函数的返回值可以直接写在箭头后
如果直接在箭头后面设置返回值时,对象字面量必须使用()括起来
const fn = () => ({"name":"张三"})
在箭头后面设置返回值,如果是形参的形式,可以不带大括号
const sum = (a, b) => a + b
<script>
/*
箭头函数的返回值可以直接写在箭头后
如果直接在箭头后面设置返回值时,对象字面量必须使用()括起来
在箭头后面设置返回值,如果是形参的形式,可以不带大括号
*/
const sum = (a, b) => a + b
const fn = () => ({"name":"张三"})
let resul = sum(1,2)
console.log(resul)
//设置一个变量result来接收执行函数的返回结果
result = fn()
console.log(result)
</script>
六十、JavaScript——全局和局部作用域
一、作用域
作用域(scope)
- 作用域指的是一个变量的可见区域
- 作用域有两种
1. 全局作用域
- 全局作用域在网页运行时创建,在网页关闭时销毁
- 所有直接编写script标签中的代码都位于全局作用域中
2. 局部作用域
- 块作用域是一种局部作用域
- 块作用域在代码块执行时创建,代码块执行完它就销毁
- 在块作用域中声明的变量是局部变量,只有在块内部访问,外部无法访问
二、全局作用域
全局作用域在网页运行时创建,在网页关闭时销毁
所有直接编写script标签中的代码都位于全局作用域中
<script>
let a = "全局变量a"
{
{
//任意位置都能访问全局变量
console.log(a)
}
}
</script>
二、局部作用域
- - 块作用域是一种局部作用域
- - 块作用域在代码块执行时创建,代码块执行完它就销毁
- - 块作用域在代码块执行时创建,代码块执行完它就销毁
<script>
// 局部作用域
{
let b = "局部变量b"
}
//块外无法访问局部变量b
console.log(b)
</script>
完整代码:
<script>
/*
作用域(scope)
- 作用域指的是一个变量的可见区域
- 作用域有两种
1. 全局作用域
- 全局作用域在网页运行时创建,在网页关闭时销毁
- 所有直接编写script标签中的代码都位于全局作用域中
2. 局部作用域
- 块作用域是一种局部作用域
- 块作用域在代码块执行时创建,代码块执行完它就销毁
- 在块作用域中声明的变量是局部变量,只有在块内部访问,外部无法访问
*/
let a = "全局变量a"
{
{
//任意位置都能访问全局变量
console.log(a)
}
}
// 局部作用域
{
let b = "局部变量b"
}
//块外无法访问局部变量b
console.log(b)
</script>
六十一、JavaScript——函数作用域
一、函数作用域
<script>
/*
函数作用域
- 函数作用域也是一种局部作用域
- 函数作用域在函数调用时产生,调用结束后销毁
- 函数每次调用都会产生一个全新的函数作用域
*/
function fn(){
let a = "fn中的变量a"
}
// 三次调用函数,三次产生新的函数作用域
fn()
fn()
fn()
</script>
六十二、JavaScript——作用域链
一、作用域链
作用域链
- 找变量的一个流程
- 当我们使用一个变量时
JS解释器会优先在当前作用域中寻找变量
如果找到了则直接使用,
如果没找到,则去上一层作用域中寻找,找到了则使用
如果没找到,则继续去上一层中寻找,
如果全局作用域都没找到,则报 xxx is not definded
使用变量遵循就近原则,在访问变量是选择离它最近的同名变量
<script>
/*
作用域链
- 找变量的一个流程
- 当我们使用一个变量时
JS解释器会优先在当前作用域中寻找变量
如果找到了则直接使用,
如果没找到,则去上一层作用域中寻找,找到了则使用
如果没找到,则继续去上一层中寻找,
如果全局作用域都没找到,则报 xxx is not definded
使用变量遵循就近原则,在访问变量是选择离它最近的同名变量
*/
let a = 10
{
let a = "第一代码块中的a"
{
let a = "第二代码块中的a"
//根据就近原则访问,离它最近的变量a
console.log(a)
}
}
</script>
六十三、JavaScript——方法
一、方法和函数的区别
方法(method)
- 当一个对象的属性指向一个函数
那么我们就称这个函数是对象的方法
调用函数就称为调用对象的方法
例如下面的 obj.sayHello(),称为调用obj的sayHello方法
调用方法: 对象.方法()
调用函数: 函数()
没有本质区别,只是调用方法需要加上对象
<script>
/*
补充内容
方法(method)
- 当一个对象的属性指向一个函数
那么我们就称这个函数是对象的方法
调用函数就称为调用对象的方法
例如下面的 obj.sayHello(),称为调用obj的sayHello方法
对象的属性也可以是函数
调用方法: 对象.方法()
调用函数: 函数()
没有本质区别,只是调用方法需要加上对象
*/
//创建对象
let obj = {}
//给对象创建属性
obj.name = "张三"
obj.age = 18
// 函数也可以称为一个对象的属性
obj.sayHello = function(){
alert("hello")
}
// 调用对象属性为函数
obj.sayHello()
</script>
六十四、JavaScript——windows对象
一、windows对象
window对象
- 在浏览器中,浏览器为我们提供了一个window对象,可以直接访问
- window对象代表的是浏览器窗口,通过该对象可以对浏览器窗口进行各种操作
除此之外window对象还负责存储JS中的内置对象和浏览器的宿主对象
- window对象的属性可以通过window对象访问,也可以直接访问
即 window.alert() 和alert() 效果是一样的
- 函数就可以认为是window对象的方法
var 用来声明变量,作用和let相同,但是var不具有块作用域
- 在全局中使用var声明的变量,都会作为window对象的属性保存
- 使用function声明的函数,都会作为window的方法保存
- 使用let声明的变量不会存储在window,而存在一个秘密的小地方
- 作用域越大,优先级越低
<script>
/*
window对象
- 在浏览器中,浏览器为我们提供了一个window对象,可以直接访问
- window对象代表的是浏览器窗口,通过该对象可以对浏览器窗口进行各种操作
除此之外window对象还负责存储JS中的内置对象和浏览器的宿主对象
- window对象的属性可以通过window对象访问,也可以直接访问
即 window.alert() 和alert() 效果是一样的
- 函数就可以认为是window对象的方法
*/
alert(window)
// 内置对象,不需要声明,直接使用
String()
Number()
//宿主对象alert、document、console.都存到了window中,不需要声明,直接使用
alert()
document.write()
console.log()
/*
var 用来声明变量,作用和let相同,但是var不具有块作用域
- 在全局中使用var声明的变量,都会作为window对象的属性保存
- 使用function声明的函数,都会作为window的方法保存
- 使用let声明的变量不会存储在window,而存在一个秘密的小地方
- 作用域越大,优先级越低
*/
//在全局中使用var声明的变量,都会作为window对象的属性保存
var b = 20
// 作为window对象的属性保存
window.b = 20
//使用function声明的函数,都会作为window的方法保存
function fn(){
alert("我是fn")
}
//使用window的方法保存
window.fn()
// 在局部作用域中,如果没有使用var或let声明变量,则变量会自动成为window对象的属性,也就是全局变量
function fn(){
d = 10 // 这里的变量d就是window对象的属性
//等价于
window.d
}
</script>
六十七、JavaScript——debug
一、debug
方式一:在代码中直接添加“debugger”打断点
<script>
debugger //在代码中打断点
let a = 10
console.log(a)
</script>
方式二:在源代码处直接点击某处,完成打断点,再刷新页面
六十八、JavaScript——立即执行函数
一、立即执行函数
立即执行函数(IIFE)
- 立即执行函数是一个匿名函数,并且它只会调用一次
- 可以利用IIFE来创建一个一次性的函数作用域,避免变量冲突的问题
- 语法:
(function(){
console.log(111)
}())
<script>
/*
在开发中应该尽量减少直接在全局作用域中编写代码
我们的代码要尽量编写到局部作用域
使用let声明的变量,可以使用{}来创建作用域,具有块作用域
但var没有块作用域,却有函数作用域
*/
// let定义的变量具有块作用域
{
let a = 10
}
{
let a = 20
}
// var定义的变量没有块作用域,但有函数作用域
// 希望可以创建一个只执行一次的匿名函数
/*
立即执行函数(IIFE)
- 立即执行函数是一个匿名函数,并且它只会调用一次
- 可以利用IIFE来创建一个一次性的函数作用域,避免变量冲突的问题
*/
(function(){
let a = 10
console.log(111)
}())
</script>
六十九、JavaScript——函数中的this
一、函数中的this
- 函数在执行时,JS解析器每次都会传递一个隐含的参数
- 这个参数叫做 this
- this会指向一个对象
- this所指向的对象会根据函数调用方式的不同而不同
1. 以函数的形式调用时,this指向的是windows
2. 以方法的形式调用时,this指向的是调用方法的对象
<script>
/*
- 函数在执行时,JS解析器每次都会传递一个隐含的参数
- 这个参数叫做 this
- this会指向一个对象
- this所指向的对象会根据函数调用方式的不同而不同
1. 以函数的形式调用时,this指向的是windows
2. 以方法的形式调用时,this指向的是调用方法的对象
*/
// 利用this指向name变量
const obj = {
name : " 沙僧",
sayHello: function(){
console.log(this.name)
}
}
// 为变量添加一个方法,可以打印自己的名字
obj.sayHello()
</script>
七十、JavaScript——箭头函数中的this
一、箭头函数中的this
箭头函数:
([参数]) => 返回值
例子:
无参箭头函数: () => 返回值
一个参数的: a => 返回值
多个参数的: (a, b) => 返回值
只有一个语句的函数: () => 返回值
只返回一个对象的函数:() => ({...})
有多行语句的函数: () => {
...
return 返回值
}
箭头函数没有自己的this,它的this由外层作用域决定的
箭头函数的this和他的调用方式无关
//一般函数
function fn(){
console.log("fn -->" , this)
}
//箭头函数
const fn2 = () => {
console.log("fn2 -->", this)
}
//函数调用
fn(); //打印结果为window
fn2(); //打印结果为window
下面的例子中,以方法的形式调用:对象.方法名()
因为箭头函数的this由外层作用域决定,这里箭头函数fn2是全局区定义的,外层作用域为全局,所以this指向window
//一般函数
function fn(){
console.log("fn -->" , this)
}
//箭头函数
const fn2 = () => {
console.log("fn2 -->", this)
}
//以方法的形式调用
const obj = {
name: "张三",
//将函数设置为对象的方法
fn: fn, //属性名: 方法名,把fn设置为obj的属性
fn2: fn2, //属性名: 方法名,把fn2设置为obj的属性
}
//以方法的形式调用:对象
obj.fn() //打印结果为window
obj.fn2() //打印结果为window
- 设置sayHello()函数中内置普通函数t和箭头函数t2
- 普通函数t以函数形式调用,控制台打印为window
- 箭头函数t2以函数形式调用,但是箭头函数的this和他的调用方法无关,与他的外层作用域有关,她的外层是sayHello(),sayHello()的this是name:张三,因此此处打印的是name:张三
//一般函数
function fn(){
console.log("fn -->" , this)
}
//箭头函数
const fn2 = () => {
console.log("fn2 -->", this)
}
//函数调用
// fn(); //打印结果为window
// fn2(); //打印结果为window
//以方法的形式调用
const obj = {
name: "张三",
//将函数设置为对象的方法
fn: fn, //属性名: 方法名,把fn设置为obj的属性
fn2: fn2, //属性名: 方法名,把fn2设置为obj的属性
sayHello(){
console.log(this.name)
function t(){
console.log("t-->",this)
}
t2 = () => {
console.log("t2-->",this)
}
//以函数形式调用
t()
//虽然是以函数的形式调用,但是箭头函数的this和他的调用方法无关,与他的外层作用域有关,她的外层是因此此处打印的是name:张三
t2()
}
}
obj.sayHello()
七十一、JavaScript——严格模式
一、严格模式
JS运行代码的模式有两种
- 正常模式
- 默认情况下代码都运行在正常模式下
在正常模式下,语法检查并不严谨
它的规则是:能不报错的地方尽量不报错
- 这种处理方式导致代码的运行性能较差
- 严格模式
- 在严格模式下,语法检查变得严谨
1. 禁止一些语法
2. 更容易报错
3. 提升了性能
- 在开发中尽量使用严格模式
这样可以将一些隐藏的问题消灭在萌芽阶段
同时也可以提升代码的运行性能
<script>
//全局的严格模式
"use strict"
//函数中使用严格模式
function fn(){
"use strict"
}
</script>