JS-函数

作者: 刘淘 | 来源:发表于2020-06-14 22:21 被阅读0次

1.函数基础 函数参数

函数写法:
function func(){}
var func=function(){}
经常使用对象来封装具有某一特定功能的函数集合,内部函数可简写为func(){}

var getName = function (name) {
    console.log(name)
}
getName('xiaoming')
const user = {
    name: null,
    getName() {
        return this.name
    },
    setName() {
        this.name = name
    }
}

函数参数

  • 函数参数分为行参和实参,建议两者数量保持一致
  • 如果行参数量大于实参数量,那未传递的形参将赋值为undefined(常用于实现函数重载)
  • 如果实参数量大于形参数量,那多余的实参将被忽略(无意义)
  • 使用短路运算符或默认参数对某些参数赋默认值,默认参数必须放在函数声明的最后
  • 使用函数参数arguments声明可变参数,但arguments不是数组,需要通过[...arguments]或Array.from(arguments)来转化
  • 使用...args来替换arguments声明可变参数,可直接使用数组的相关方法
    +使用...扩展运算符声明参数,但必须放到函数声明的最后,甚至是默认参数的最后
// 形参&实参
function sum(a, b) {
    console.log(a, b)
}
sum(1)        // 1, undefined
sum(1, 2, 3)  // 1, 2
// 默认参数
function avg(year = 1, total) {
    // year = year || 1
    return Math.round(total / year)
}
console.log(avg(3000))      // 3000
console.log(avg(3000, 2))   // 1500
function sort(arr, type = 'asc') {
    return arr.sort(function (a, b) {
        return type === 'asc' ? a - b : b - a
    })
}
console.log(sort([1, 3, 4, 2, 5]))
console.log(sort([1, 3, 4, 2, 5], 'desc'))

//利用扩展运算符计算arguments
function sum1() {
    return [...arguments].reduce((a, b) => a + b)
}
function sum2() {
    return Array.from(arguments).reduce((a, b) => a + b)
}
console.log(sum1(1, 1))
console.log(sum1(11, 11))
//使用扩展运算符声明参数,必须放到最后
function totalDisPrice(discount = 0, ...price) {
    return price.reduce((a, b) => a + b) * (1 - discount)
}
console.log(totalDisPrice(.1, 100, 200))



2.全局函数

  • 使用function func() 或者var func=function()定义的函数全都会直接挂载到window上,成为全局函数
  • 全局函数可能与window上已有成员冲突,造成全局污染
  • 建议不要独立定义函数,而是要将函数放在对象或类的内部去定义
//window自带的函数
console.log(window.screenX)
var screenX = function () {
    console.log('获取x轴的位置')
}
//覆盖window上已有成员,造成全局污染
console.log(window.screenX)
//放在一个对象上,避免覆盖window已有成员
const position = {
    screenX() {
        console.log('获取x轴的位置')
    },
}
console.log(position.screenX)

3.匿名函数

  • 使用var func=function()定义匿名函数,同时函数是引用类型
  • 函数表达式function func(){}与匿名函数var func=functioin(){}的区别:函数表达式存在变量提升,匿名函数不存在


    image.png

4.立即执行函数

  • 立即执行函数不需要外部调用,只需引入即可执行,格式:(function(){})()
    *立即执行函数常用于构建第三方插件库
    *立即执行函数解决第三方库与业务库之间的命名冲突问题,当然也可以使用模块化来解决
(function(){
    console.log('somethig is wrong')
})()
//第三方库js:vendor.js
; (function (window) {
    'use strict'
    const getName = function () {
        console.log('from vendor:vendor Name')
    }
    window.vendor = { getName }
})(window)

//业务库 app.js
{
    const getName = function () {
        console.log('from app:app Name')
    }
    window.app = { getName }
}
//立即执行函数解决库之间的命名冲突问题
///在同一个页面引入vendor.js app.js
vendor.getName() //from vendor:vendor Name
app.getName() //from app:app Name


5.回调函数

  • 回调函数即在其他函数的内部调用,以匿名函数
  • 回调函数常用于事件处理,数组操作
 //<button name="callback">回调</button>
document.querySelector('[name="callback"]').addEventListener('click', function() {
      alert(this.innerHTML)
    })
    const nums = [1, 2, 3, 4, 5]
    // [10, 20, 30, 40, 50]
    console.log(nums.map(function(item) {
      item = item * 10
      return item
    }))

6.递归函数

  • 递归函数即不断重复调用自身,直到有返回结果为止
  • 递归函数类似入栈 出栈,当递归开始时会依次将每一次递归表达式入栈,当有返回结果时依次将结果传递到上一层的表达式出栈
// 阶乘
const factorial = function (num) {
    // if (num === 1) return 1
    // return num * factorial(num - 1)
    return num === 1 ? 1 : num * factorial(num - 1)
}
console.log(factorial(2))        // 120
// 求和
const sum = function (...args) {
    // if (!args.length) return 0
    // return args.pop() + sum(...args)
    return !args.length ? 0 : args.pop() + sum(...args)
}
console.log(sum(1, 2, 3, 4, 5))  // 15

7.箭头函数

  • 使用箭头函数可极大简化代码编写,去掉之前的function关键字,格式:()=>{}
  • 当箭头函数只有一个参数时,可去掉()
  • 当箭头函数体只有一句话时,可去掉{}
  • 箭头函数无法解决递归 构造函数 事件处理等场景
const sum = function (...args) {
    return args.reduce(function (a, b) {
        return a + b
    })
}
//当箭头函数体只有一句话时,可去掉{}
const sum = (...args) => {
    return args.reduce((a, b) => {
        return a + b
    })
}
const sum = (...args) => args.reduce((a, b) => a + b)
console.log(sum(1, 2, 3, 4, 5))

8.this指针

  • 函数定义在类或对象的内部,称之为方法
  • 在方法内部可以使用this获取对象的所有成员,包括方法本身
  • 在方法内部在定义函数,函数内部的this则是window,而不是对象本身
  • 如果想再方法内部函数中获取当前对象,可以使用常量或者箭头函数来改变this指针


    image.png
    image.png
    image.png
    image.png
    image.png
  • 在对象中定义DOM事件回调函数,可使用function或箭头函数
  • 如果是function,当前this则是指向当前DOM元素
  • 如果是是箭头函数,当前this指向的是当前对象 本身
  • 如果同时需要获取当前DOM对象和对象本身,对function而言使用常量解决,对箭头函数而言使用event
  • 如果同时对多个DOM元素定义事件回调函数,建议保持纯净性:要么都使用function,要么都使用箭头函数
//eg: <button name='landiao'>蓝调</button>
//eg: <button name='dianyin'>电音</button>
const music = {
    name: '音乐',
    show() {
        const landiao = document.querySelector('[name="landiao"]')
        const dianyin = document.querySelector('[name="dianyin"]')
        const _this = this
        landiao.addEventListener('click', function () {
            console.log(this) //<button name='landiao'>蓝调</button>
            console.log(`${_this.name}-${this.innerHtml}`)//音乐-蓝调
        })
        dianyin.addEventListener('click', (e) => {
            console.log(this) //{name:'音乐',show:f} 箭头函数的this就是定义时所在的对象
            console.log(`${this.name}-${e.target.innerHtml}`) //音乐-电音
        })
    },
    bind() {
        const buttons = document.querySelectorAll('button')
        buttons.forEach((item) => {
            console.log(this) //箭头函数的this就是其定义时所在的对象{name:'音乐',show:f,bind:f} 
            item.addEventListener('click', (e) => {
                console.log(this)  //箭头函数的this就是其定义时所在的对象{name:'音乐',show:f,bind:f}
                console.log(`${this.name}-${e.target.innerHTML}`)
            })
        })
    }
}
user.show()
user.bind()

9.call apply bind

  • 使用call apply改变this指针的指向,将this指向当前传入的对象,且函数会立即执行
  • call apply的区别:call可传入多个参数,apply只能传入数组
    *使用bind也能改变this指针的指向,将this指向当前传入的对象,但函数不会立即执行,同时返回一个函数
  • 使用bind传参有两种方式:定义时传参(优先)或调用是传参
  • 使用bind常用于处理事件回调从外面传入参数
//eg: <button name='landiao'>蓝调</button>
//eg: <button name='dianyin'>电音</button>
const user = {
    name: 'xiaoming',
}
function Person(url,skills){
    console.log(this.name,url,siklls)
}
Person.call(user,'http://baidu.com',['蓝调','电音'])
Person.apply(user,['http://baidu.com',['蓝调','电音']])
//bind bind bind start 
const fun1=Person.bind(user) //bind返回的是一个函数,不会立即执行
fun1('http://baidu.com',['蓝调','电音']) //bind的传参方式
const fun2=Person.bind(user,'http://baidu.com',['蓝调','电音'])
fun2() //执行bind返回的函数
//bind bind bind end

//应用1
function showInnerHtml(){
    alert(this.innerHtml())
}
const buttons=document.querySelectorAll('button')
buttons.forEach(item=>{
    item.addEventListener('click',(e)=>{
        show.call(e.target)
    })
})
//应用2 随机切换背景图
function Color(elem) {
    this.elem = elem
    this.colors = ['#9b59b6', '#1abc9c', '#34495e', '#e74c3c', '#f39c12']
    this.run = function () {
        setInterval(function () {
            //Math.floor向上取整 Math.random随机 (0~1)
            const index = Math.floor(Math.random() * this.colors.length)
            this.elem.style.backgroundColor = this.colors[index]
        }.bind(this), 1000)
    }
}
const color = new Color(document.body)
color.run()
  • 使用call apply实现类的继承,对已有的功能执行复用
function Request() {
    this.get = (params) => {
        const query = Object.keys(params).map(item => `${item}=${params[item]}`).join('&')
        const url = `http://baidu.com/${this.url}?${query}`
        console.log(url)
    }
}
// 继承
function Article() {
    this.url = 'article/list'
    Request.call(this)
    // Request.apply(this)
}
function User() {
    this.url = 'user/list'
    Request.call(this)
    // Request.apply(this)
}
const article = new Article()
const user = new User()
article.get({ id: '1', cat: 'js' })             // http://baidu.com/article/list?id=1&cat=js
user.get({ name: 'miracle', role: 'admin' })    // http://baidu.com/user/list?name=miracle&role=admin

相关文章

  • JS-函数

    事件驱动模型: 事件(操作,动作) 事件类型(具体的动作类型) 事件源(发生动作的地方) 事件监听器(监听事件发生...

  • JS-函数

    1.定义(1)匿名函数(2)具名函数(3)箭头函数,无this 词法作用域(也叫静态作用域)JS看到上面的代码不是...

  • JS-函数

    1.函数基础 函数参数 函数写法:function func(){}var func=function(){}经常...

  • JS-函数

    函数1.声明 function 函数名(参数1,参数2...){ 函数体 retur...

  • js-函数

    函数

  • js-工具函数

    日常总结 秒转时分秒

  • Js-函数-6.1

    1 :Try{}catch(){}finally{}catch会捕获到前面抛出的异常,无论是直接抛出的还是函数调用...

  • js-函数进阶

    函数(function)把要执行的代码放入函数里面,使其函数里面的代码反复被使用,减少了大量代码累跌 函数的基本书...

  • 关于 JS-函数

    1. 函数声明和函数表达式有什么区别 函数声明就是定义一个函数,如以下例子 function text(){ //...

  • js-函数练习

    函数练习

网友评论

    本文标题:JS-函数

    本文链接:https://www.haomeiwen.com/subject/nortxktx.html