05 js函数

js函数

创建一个函数

function fn() {
  console.log("你好")
  console.log("hello")
  console.log("阿尼哈赛有")
  console.log("口你急哇")
}
fn(); //调用函数
console.log(typeof fn) //返回function

把一些语句存储在函数中, 在需要时进行调用

创建方式

//1, 一般创建方式(函数声明)
function fn() {
    console.log("函数声明定义的函数")
}
//2, 函数表达式(匿名函数)
	//function() 没有函数名, 因此需要定义一个变量来接收
let fun2 = function() {
    console.log("函数表达式定义的函数")
}
//3, 箭头函数
let fn3 = () => {
    console.log("箭头函数")
}
//函数内只有一个语句时可以省略 {}与()
let fun4 = () => console.log("箭头函数")

函数的参数

function fn(a, b) { //a, b 为形式参数
    console.log(a + b)
}
fn(1, 2) //1, 2 为实际参数
cosnt fn2 = (a=10, b=20, c=30) { //可以传递默认参数
    console.log(a, b, c)
}
fn2(1, 2)

形式参数: 在定义函数时, 可以在函数中指定一些形参, 在函数中定义的形参, 相当于在函数内部声明了一个变量但是没有赋值

实际参数: 在调用函数时, 可以在函数的()传递一些实参, 实参会赋值给形参

js不会检查参数的类型, 可以传递任意类型的值作为参数

默认参数: 没在函数调用时, 传递实参, 就会传递默认参数

对象参数

function fn(a) {
  console.log(a);
  a.name = "猪八戒" //改对象
  a= {} // 改变量
  console.log(a);
  console.log(a.name)
}
let obj = {name: "孙悟空"}
fn(obj)

传递参数时, 传递的并不是变量本身, 而是变量中存储的值, 因此也有改变量与改对象区别

//传入形参对象 (每次函数调用都会创建一个新的对象, 每次调用都为不同的对象)
function fn(a = {name: "张三"}) {
  console.log("a = ", a)
  a.name = "唐僧"
  console.log("a = ", a)
}
fn() //张三 唐僧
fn() //张三 唐僧
//在函数外面创建对象, 然后赋值给形参(函数每次调用都为obj对象, 每次调用始终都为一个对象)
let obj = {name: "李四"}
function fn2(a = obj) {
  console.log("a = ", a)
  a.name = "唐僧"
  console.log("a = ", a)
}
fn2()//李四 唐僧
fn2()//唐僧 唐僧

函数每次调用都会重新创建默认值, 因此对象作为形参时, 每次调用就会创建一个新的对象

函数参数

function fn (a) {
  a()
}
function fn2() {
  console.log("我是fn2")
}
//函数作为参数传递
fn(fn2)
fn(function() {
  console.log("我是匿名函数")
})
fn(() => {
  console.log("我是箭头函数")
})

函数的返回值

function fn() {
  // return "hello"
  // return {name: "李四"}
  return () => alert(123)
}
let result = fn()
console.log(result)
//箭头函数的返回值 (返回值只有一个时, 可以省略 {} 与 return关键字)
const fn2 = () => ({name: "张三"}) // 返回对象(返回对时, 要套一个括号, 避免{}冲突)
const fn2 = () => () => alert(456) // 返回函数
console.log(fn2())
//return后 不跟返回值, 或者不写return 都会打印undefined
function fn(a) {
  return 
}
let result = fn()
console.log(result)

使用return关键字来指定函数的返回值 (可以控制函数返回结果, 不会直接在调用函数时就进行打印) , 返回值就是函数执行的结果, 函数调用完毕返回值就会作为结果返回, 函数的返回值可以指定任何类型值, 且return一旦执行则函数立即终止

函数的作用域

作用域 : 指一个变量的可见区域

let a = "全局"
{
  let b = "局部1"
  {
    let c = "局部2"
    conloe.log(a, b, c) //可以访问到所有的变量(a,b,c)
  }
}
console.log(a)// 只访问到变量a

全局作用域: 生命周期 --> 在网页运行时创建, 在网页关闭时销毁

直接编写在script标签下的代码都为全局作用域, 其中的变量为全局变量(包括函数与对象等), 可以在任何地方访问

局部作用域: 生命周期 --> 在代码块执行时创建, 代码块实行完毕时销毁

在局部作用域声明的变量(包括函数与对象等) 只能在代码块内部(包括子代码块)访问, 外部无法访问

函数作用域 :

function fn() {
    let a = "fn中的变量"
    console.log(a)
}
fn()
console.log(a) //a未定义

函数作用域: 是一种局部作用域 只能在函数内部访问, 在函数调用时创建, 调用完毕后销毁, 函数的每次调用都会产生一个新的函数作用域,

作用域链

let b = 11
function fn() {
    let b = 22
    function fn2() {
        console.log(b)
    }
    fn2()
}
fn()// b=22

作用域链(就近原则): 当使用一个变量时, 会在当前作用域内寻找, 如果没有则到上一层作用域去寻找, 直到找到全局作用域, 如果还没有则报错

方法

let obj = {}
obj.name = "张三"
obj.age = 18
obj.sayHello = function(){
    alert("hello")
}
console.log(obj)
obj.sayHello()

方法: 当一个对象指向一个函数, 则该函数就是这个对象的方法, 调用函数就是调用对象的方法

window对象

window.alert(123)
window.console.log(456)
window.a = 10 //向window对象中添加的属性会自动转化为全局变量
console.log(a)

window对象: 在浏览器中, 为我们提供了一个window对象, 可以直接访问. window对象代表浏览器窗口, 通过该对象可以对浏览器窗口进行各种操作, window对象还负责存储js中的内置对象与宿主对象, window对象的属性可以window对象访问, 也可以直接访问, 函数可以认为是window对象的方法

function fn() {
    let a = 11 
    var a = 22 //var 虽然没有块作用域, 但存在函数作用域
    a = 33 //在局部作用域中如果没使用 var 与 let 则会自动成为window对象的属性(全局变量)
}
fn()
console.log(a)

提升

//变量的提升
//var声明的变量
console.log(a) //undefined
var a = 10
//let声明的变量
console.log(b) //初始化前不能访问
let b = 20
//函数的提升
fn()
function fn() {
    alert("fn的函数")
}

变量的提升:

使用var声明的变量, 会在所有代码执行前被声明, 因此可以在变量声明前访问变量

**使用let声明的变量, **实际上也会被提升, 但在赋值之前js解释器会禁止对该变量的访问

函数的提升:

使用函数声明(必须是以 function 开头创建的函数, 不能是匿名, 箭头函数)创建的函数, 会在其他代码执行前被创建, 因此可以在函数声明前调用函数

立即执行函数

//let定义变量, 可以使用代码块来创建块作用域, 避免变量冲突
{let a = 10}
{let a = 20}
//var定义变量, 可以使用立即执行函数,创建一个函数作用域,来避免变量的冲突
(function(){
    console.log(111)
}()); //这个 ; 号一定要手动添加, 否则js会解释成()()函数调用
(function(){
    console.log(222)
}());

立即执行函数: 立即执行函数是一个匿名函数, 并且只会调用一次, 可以用来创建一个一次性的函数作用域, 避免变量冲突的问题

函数中的this

function fn() {
    console.log("fn调用",this)
}
fn() // --> window.fn() this-->window
const obj = {name:"张三"}
obj.test = fn //this-->obj1
const obj2 = {name:"李四", test: fn} // this-->obj2
const obj3 = {
    name: "沙和尚"
    sayHello: function() {
        console.log(this.name)//this-->name(沙和尚)
    }
}
const obj4 = {
    name: "唐僧"
    sayHello: function() {
        console.log(this.name)//this-->name(唐僧)
    }
} 
obj3.sayHello()//修改name的值就会修改sayHello的返回值
obj4.sayHello()

函数在执行时,js解释器每次都会传递进一个隐含的参数–>this, this会指向一个对象, 这个对象会根据函数调用的方式不同而不同, 以函数形式调用时, this会指向window, 以方法的形式调用时, this指向的是调用方法的对象

通过this可以在方法中引用调用方法的对象(如obj3与obj4)

箭头函数中的this

const fn() {
    console.log(this) //this-->fn
}
const fn2 = () => {
    console.log(this) //this --> window
}
const obj = {
    name: "张三",
    fn, //属性名与属性值相同可以简化
    fn2,
    sayHello() {
        console.log(this.name) //张三
        const t() {
            cosnole.log(this) //this --> window
        }
        t()
        const t2 = () => {
            console.log(this) //张三
        }
        t2()
    }
}
obj.sayHello()

箭头函数没有自己的this, 它的this由外层作用域决定, 箭头函数的this和他的调用方式无关

严格模式

//全局严格模式
"use strict"
//函数严格模式
function fn() {
"use strict"
}

在严格模式下, 会禁止一些语法, 更容易报错, 提高代码执行性能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值