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"
}
在严格模式下, 会禁止一些语法, 更容易报错, 提高代码执行性能