想品客老师的第六天:函数

函数基础的部分写在这里

函数声明

在js里万物皆对象,函数也可以用对象的方式定义

    let func = new Function("title", "console.log(title)");func('我是参数title');

也可以对函数赋值:

  let cms = function (title) {console.log(title);};//表达式这里有写分号cms("后盾人");

es6新增了简写模式

举个栗子:围绕对用户模块的设置,在对象里面写方法

       let user = {name: null,setUsername(name) {this.name = name;},getUsername() {return this.name;}};user.setUsername("荷叶饭");console.log(user.getUsername());//荷叶饭

正常情况对方法的声明应该是【setUsername:function(){this.name-name;}】

es6的简写是【 setUsername(name) {this.name = name;}】可以不用写冒号和function

全局函数定义特点

我们普通的在全局写一个函数,会把函数托到全局上,自动给他一个window对象:

   function screenX(){console.log('我是screenX函数,已经有一个和我一样的函数名了')}console.log(window.screenX)

像这样:

但是实际上window里本来就有一个screenX属性,他们名字一样,新的会覆盖旧的,旧的旧不起作用了

    console.log(window.screenX)//返回浏览器左边界到操作系统桌面左边界的水平距离。

这就是全局变量的缺点

匿名函数

匿名函数就是没名字的函数,函数的调用可以写在函数的声明前

   show()//荷叶饭function show() {console.log('荷叶饭')}

这叫函数提升 函数提升看这里

函数的本质也是个对象

 console.log(hd instanceof Object)//true

立即执行函数与块作用域解决冲突

在引入其他人的库的时候,会出现函数名重复的问题,解决办法有两个:模块化类的思想和立即执行函数(之前也讲过)

在引入外来库的时候,我们可以通过自己给库私有化:

  <script src="./0124Js1.js"></script><script src="./0124Js2.js"></script><script>js1.hd()//把两个名字一样的函数封装在两个不要太的对象里js2.hd()//这样就不会冲突了</script>

看看立即执行函数:

js1:

(function(window) {function hd() {console.log("4.1.js-hd");}function show() {console.log("4.1.js-show");}window.js1 = { hd, show };
})(window);//不加window在全局调用不了,所以把它封装在window里

js2:

(function (window) {//把window传入function hd() {console.log("4.2.js-hd");}function show() {console.log("4.2.js-show");}window.js2 = { hd, show };
})(window);//把window传入

  作用域也可以看这里

形参和实参

形参就是函数里占位置的,形参的数量一般要和实参的数量对应

默认参数

给形参设置默认值

   function avg(total, year = 1) {console.log(year);//year=1return Math.round(total / year);}console.log(avg(2000))//year=1当作默认值传入函数,结果等于2000

 再举一个例子:

    function sortArray(array, type = "asc") {return array.sort((a, b) => (type == "asc" ? a - b : b - a));}console.log(sortArray([3, 1, 4, 2], "asc"));

这时候就按升序排序,如果传递的实参不是asc,按降序:

        function sortArray(array, type = "asc") {return array.sort((a, b) => (type == "asc" ? a - b : b - a));}console.log(sortArray([3, 1, 4, 2], "dasc"));

默认参数一般放在后面,放在后面在传递实参的时候可以不传,但是放在前面必须传递undefined:

 function sortArray(array, type = "asc") {return array.sort((a, b) => (type == "asc" ? a - b : b - a));}console.log(sortArray([3, 1, 4, 2]))//不报错
     function sortArray(type = "asc",array ) {return array.sort((a, b) => (type == "asc" ? a - b : b - a));}console.log(sortArray(undefined,[3, 1, 4, 2]))//传undefined不报错

函数参数

函数的参数也可以是函数,在filter里传函数:

       function fun(a) {return a <= 3}let arr = [1, 2, 3, 4, , 5, 6, 7].filter(fun)console.log(arr)//[1,2,3]

还讲到了参数不定数的时候,使用arguments参数,也就是可变参数,动态参数

arguments的一个属性:length,获取到的参数的长度

 function sum() {console.log(arguments.length)//6}console.log(sum(1, 2, 35, 4, 6, 22))

arguments本质上是一个对象:

function sum() {console.log(typeof arguments)//object}console.log(sum(1, 2, 35, 4, 6, 22))

剩余参数

也可以用剩余参数:

剩余参数:函数参数使用,得到真数组,吸收

展开运算符:数组中使用,数组展开,释放

   function sum(...args) {return args.reduce((a, b) => a + b);}console.log(sum(1, 23, 3, 43, 45, 53))//168

箭头函数

此事在这篇博客里亦有记载

递归、构造、事件处理的时候都用不了箭头函数

递归

边界条件和递归方程组成,这是阶乘的递归组成:

     function factorial(num) {if (num == 1) return 1return num * factorial(num - 1)}console.log(factorial(5))//5的阶乘=120

更简单的写法可以这么写:

function factorial(num) {return num == 1 ? 1 : num * factorial(--num);}console.log(factorial(5))//5的阶乘=120

写一个递归求和

  function sum(...args) {console.log(args)if (args.length == 0) {return 0}return args.pop() + sum(...args)}console.log(sum(1,2,3,4,5))

递归实现倒三角

        function star(sum) {return sum? document.write("*".repeat(sum) + "<br/>") || star(--sum): "";}star(5);

递归渲染

function change(lessons, num = 100, i = 0) {if (i == lessons.length) {return lessons;}lessons[i].click += num;return change(lessons, num, ++i);//i必须是++i,不能是i++,因为i需要先自增再传递,如果//++的话,传递给函数change的i永远是0}console.table(change(lessons, 90));

渲染:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta http-equiv="X-UA-Compatible" content="ie=edge" /><title>后盾人</title></head><body></body><script>let lessons = [{title: "媒体查询响应式布局",click: 89},{title: "FLEX 弹性盒模型",click: 45},{title: "GRID 栅格系统",click: 19},{title: "盒子模型详解",click: 29}];lessons = lessons.map(function(item) {item.click += 100;return item;});console.table(lessons);</script>
</html>

先写到这吧。。今天舟车劳顿好累好困

回调函数

把一个函数当成另一个函数的参数传过去,在这另一个函数的某个时刻会调用

比如这个:

 document.getElementById('bt').addEventListener('click',function(){console.log('我就是个回调函数')})

回调函数的使用非常多:

被画出来的就是回调函数的部分

展开语法的收放

此事在品客老师的课中亦有记载

点语法在左边,也就是声明部分,就是【收】;在右边就是【放】

  let [...edu]=[1,2,3,4]console.log(edu)//收let hd=[1,2,3]let [a,b,c]=[...hd]console.log(a,b,c)//放

收放自如的点语法捏

展开语法用作函数的剩余参数

function sum(...args){console.log(args)return args.reduce((a,b)=>a+b)
}
console.log(sum(1,2,3,4,5,77,2))//94

函数里的this

对象里的方法(方法也是函数)的this就是指向这个对象的:

    let edu = {site: "后盾人",show: function() {console.log(this);//this指向obj}};console.log(edu.show());

当我们在方法里写一个普通函数的时候:

  let edu = {site: "后盾人",show: function() {console.log(this);//这是个方法,这个方法的this是objfunction render() {console.log(this)//render是个托管到全局的函数,所以this是window}render();//调用一下}};console.log(edu.show())//上面的方法没写返回值,所以是undefined

这个render函数是window的,所以它访问不了edu里的属性【site】(此事在作用域内亦有记载)

比如我们用构造函数这么写:

 function User(name) {this.name = name;this.show = function () {return this.name;};}let lisi = new User('李四');console.log(lisi.show());

就可以访问到name,但是在方法里再写一个函数,这个函数就访问不到:

  function User(name) {this.name = name;this.show = function () {function render() {console.log(this);//window}render();return this.name;//李四};}let lisi = new User('李四');console.log(lisi.show());

改变this指针

通过常量

可以设置一个常量等于对象this,在方法里的函数里调用这个常量

不用担心这个函数里找不到这个常量,js的机制会循着作用域链往上找的

  let Lesson = {site: "后盾人",lists: ["js", "css", "mysql"],show: function () {const self=thisreturn this.lists.map(function (value) {return `${self.site}-${value}`});}};console.table(Lesson.show());

也有的函数里面有thisArg,这个参数就是改变当前this指向的参数,比如map函数:

 let Lesson = {site: "后盾人",lists: ["js", "css", "mysql"],show: function () {return this.lists.map(function (value) {return `${this.site}-${value}`}, this);}};console.table(Lesson.show());

效果是一样的

通过箭头函数

箭头函数改变原理匿名函数this的指向

let Lesson = {site: "后盾人",lists: ["js", "css", "mysql"],show: function () {return this.lists.map(title=>`${this.site}-${title}`);}};console.table(Lesson.show());

有时候我们不想让匿名函数的this指向全局,也不想指向上一级,如果有事件的话,可以使用event参数,也就是之前学的事件对象,使用event+箭头函数,可以让this指向会被触发的事件的对象

 let Dom={site:'荷叶饭',bind:function(){const button=document.querySelector('button')button.addEventListener('click',event=>{console.log(this)console.log(this.site+event.target.innerHTML)})}}
Dom.bind()

    在普通函数中,this 指向触发事件的元素(即 button)因此,this.site 会是 undefined,因为 button 元素没有 site 属性。

    MDN上有addEventListener的参考,aEL第二个参数可以是一个函数或者是一个实现了EventListener接口的对象,也就是说this可以当第二个参数:

    const button = document.querySelector("button");button.addEventListener("click", this);console.log(button);
    

    总之箭头函数的this指向父级的this,普通函数的this指向window,具体使用看具体情况

    构造函数怎么构造对象的:通过对构造函数里的this的属性名增删改查,new的时候创建对象

    call、bind、apply

    call会立即调用构造函数

    apply也会立即调用构造函数

    在这里再讲讲为什么这里可以传入Math:

    首先Math是什么?没错是个js的内置对象,Math.max()是一个方法,更是一个函数

    apply是什么?是函数的方法

    那Math.max.apply这句是不是没有问题,因为apply是函数的方法,而Math.max()就是个函数啊!

    apply的第一个参数是什么?是thisArg,改变this指向,传入Math就是把指向改为Math,没问题吧!

    所以可以借用数学运算求数组的最大值

    如果想让bind执行就加个括号:

    function show(){console.log(this.name)}show.bind({name:'荷叶饭'})()//有反应,执行了函数,打印this.name=荷叶饭
          function show(){console.log(this.name)}show.bind({name:'荷叶饭'})//没有反应

    还有就是经过bind的两个对象不相等:

      let a = function () { };let b = a;console.log(a === b);//trueb = a.bind();console.log(a === b);//false

    因为call和apply这两个方法是立即调用函数的,立即调用函数就得把参数传上

    而bind不立即执行,所以可以在执行的时候再传参:

     function fun(a,b){console.log(a,b)return this.f+a+b            }let func=fun.bind({f:1})//改变指向func(3,4)//这一步真正执行:3,4

    如果在bind的时候传了一个参数,那么在执行的时候传的两个参数,后面那个就多出来了:

      function fun(a,b){console.log(a,b)return this.f+a+b            }let func=fun.bind({f:1},3)//改变指向func(3,4)//这一步真正执行:3,3

    bind这种不立即执行的方法就适用在事件处理上,因为只有事件触发的时候才执行:

     document.querySelector("button").addEventListener("click",function (event) {document.write(this.url + event.target.innerHTML);}.bind({ url: "你点击了我" }));

    对bind加深印象:

    <!DOCTYPE html>
    <html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta http-equiv="X-UA-Compatible" content="ie=edge" /><title>后盾人</title></head><style>* {padding: 0;margin: 0;}body {width: 100vw;height: 100vh;font-size: 3em;padding: 30px;transition: 2s;display: flex;justify-content: center;align-items: center;background: #34495e;color: #34495e;}h1 {padding: 30px;font-size: 30px;}</style><body><h1>houdunren.com</h1>houdunren.com</body><script>function Color(elem) {this.elem = elem;this.colors = ["#1abc9c", "#f1c40f", "#9b59b6", "#f39c12"];this.run = function() {setInterval(function() {let i = Math.floor(Math.random() * this.colors.length);this.elem.style.backgroundColor = this.colors[i];}.bind(this),1000);};}let obj = new Color(document.body);obj.run();let h1 = new Color(document.querySelector("h1"));h1.run();</script>
    </html>
    

    构造函数方法继承

    例如现在向后台请求url可以多个构造函数复用方法:

        function Request() {this.get = function(params) {let str = Object.keys(params).map(k => `${k}=${params[k]}`).join("&");let url = `https://api.houdunren.com?${this.url}/${str}`;document.write(url + "<hr/>");};}//https://houdunren.com/article/lists?id=1&cat=jsfunction Article() {this.url = "article/lists";Request.apply(this);}let a = new Article();console.log(a.get({ id: 1, cat: "js" }));function User() {this.url = "user/lists";Request.call(this);}let user = new User();user.get({ id: 2, role: "admin" });

    举个栗子:

    <!DOCTYPE html>
    <html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta http-equiv="X-UA-Compatible" content="ie=edge" /><title>后盾人</title>
    </head>
    <style>* {padding: 0;margin: 0;}body {display: flex;justify-content: center;align-items: center;width: 100vw;height: 100vh;}dl {width: 400px;display: flex;flex-direction: column;}dt {background: #e67e22;border-bottom: solid 2px #333;height: 50px;display: flex;justify-content: center;align-items: center;cursor: pointer;}dd {height: 200px;background: #bdc3c7;font-size: 5em;text-align: center;line-height: 200px;}
    </style><body><dl><dt>上一页</dt><dd>1</dd><dt>下一页</dt><dd hidden="hidden">2</dd></dl>
    </body>
    <script>function panel(i) {let dds = document.querySelectorAll("dd");dds.forEach(dd => dd.setAttribute("hidden", "hidden"));dds[i].removeAttribute("hidden");}document.querySelectorAll("dt").forEach((dt, i) => {dt.addEventListener("click", () => panel.call(null, i));});
    </script></html>

    孩子们我要学疯了

    本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/7315.html

    如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

    相关文章

    Python:元组构造式和字典推导式

    &#xff08;Python 元组构造式和字典推导式整理笔记&#xff09; 1. 元组构造式 1.1 创建元组 使用圆括号&#xff1a; tuple1 (1, 2.5, (three, four), [True, 5], False) print(tuple1) # 输出: (1, 2.5, (three, four), [True, 5], False) 省略圆括号&#xff1a; tup…

    Linux之Tcp粘包笔记

    目录 一.网络传输四层模型 二.数据传输中数据包传输的两个限制概念 三.数据传输的中粘包问题 四.数据组装的原因 Nagle算法原理: 五.关闭Nagle优化处理粘包问题吗&#xff1f; 六.粘包处理方法 a.设置消息边界&#xff1a; b.定义消息长度&#xff1a; 七.UDP是否会出…

    【C语言算法刷题】第2题 图论 dijkastra

    题目描述 一个局域网内有很多台电脑&#xff0c;分别标注为 0 ~ N-1 的数字。相连接的电脑距离不一样&#xff0c;所以感染时间不一样&#xff0c;感染时间用 t 表示。 其中网络内一台电脑被病毒感染&#xff0c;求其感染网络内所有的电脑最少需要多长时间。如果最后有电脑不…

    软件测试压力太大了怎么办?

    本文其实是知乎上针对一个问题的回答&#xff1a; 目前在做软件测试&#xff0c;主要负责的是手机端的项目测试&#xff0c;项目迭代很快&#xff0c;每次上线前验正式都会发现一些之前验测试包时候没有发现的问题&#xff0c;压力太大了&#xff0c;应该怎么调整 看过我之前其…

    枚举与模拟 练习

    练习题基于《C/C程序设计竞赛真题实战特训教程&#xff08;图解版&#xff09;》 目录 1.1 卡片 题目描述 代码实现 题解笔记 总评 注意点 重点解释 1.2 回文日期 题目描述 输入描述 输出描述 代码实现 题解笔记 总评 注意点 重点解释 1.1 卡片 题目描述 小蓝…

    Redis高阶5-布隆过滤器

    Redis布隆过滤器 ​ 由一个初始值都为零的bit数组和多个哈希函数构成&#xff0c;用来快速判断集合中是否存在某个元素 目的减少内存占用方式不保存数据信息&#xff0c;只是在内存中做一个是否存在的标记flag 布隆过滤器&#xff08;英语&#xff1a;Bloom Filter&#xff0…

    vim如何设置自动缩进

    :set autoindent 设置自动缩进 :set noautoindent 取消自动缩进 &#xff08;vim如何使设置自动缩进永久生效&#xff1a;vim如何使相关设置永久生效-CSDN博客&#xff09;

    检测到联想鼠标自动调出运行窗口,鼠标自己作为键盘操作

    联想鼠标会自动时不时的调用“运行”窗口 然后鼠标自己作为键盘输入 然后打开这个网页 &#xff08;不是点击了什么鼠标外加按键&#xff0c;这个鼠标除了左右和中间滚轮&#xff0c;没有其他按键了&#xff09;

    (Halcon)轮廓等分切割(项目分析)

    目标&#xff1a;获取绿色圆所在位置&#xff08;可用于点焊/点胶引导&#xff09; 实现思路 一&#xff0c;相机标定板标定&#xff08;如果实战用于点焊/点胶引导需要做图像畸变校正以减小误差&#xff09; 相机标定 如何做一个C#仿Halcon Calibration插件-CSDN博客 二&…

    Java面试题2025-Mysql

    1.什么是BufferPool&#xff1f; Buffer Pool基本概念 Buffer Pool&#xff1a;缓冲池&#xff0c;简称BP。其作用是用来缓存表数据与索引数据&#xff0c;减少磁盘IO操作&#xff0c;提升效率。 Buffer Pool由缓存数据页(Page) 和 对缓存数据页进行描述的控制块 组成, 控制…

    开始步入达梦中级dba

    分析内存使用需要的方法之一 disql /nolog conn sysdba/sysdbaselect value from v$parameter where nameMEMORY_LEAK_CHECK; SP_SET_PARA_VALUE(0,MEMORY_LEAK_CHECK,1); select * from V$MEM_REGINFO; select * from V$MEM_HEAP;

    UE求职Demo开发日志#7 强化属性完善

    1 实现思路设计 定义一个结构体记录技能树一个单元的信息&#xff0c;命名为FStrengthenCellInfo&#xff0c;一个TArray记录技能树整体信息&#xff0c;需要以下信息&#xff1a; 1.TArray前置技能index 2.FString 描述文本 3.TArray<FMyItemInfo>激活需要的物品ID和…

    Qt中QVariant的使用

    1.使用QVariant实现不同类型数据的相加 方法&#xff1a;通过type函数返回数值的类型&#xff0c;然后通过setValue来构造一个QVariant类型的返回值。 函数&#xff1a; QVariant mainPage::dataPlus(QVariant a, QVariant b) {QVariant ret;if ((a.type() QVariant::Int) &a…

    做Midjourney最好图文教程-提示词公式以及高级参数讲解

    先说Midjourney万能公式 填写在绘图提示词框里的内容就是提示词&#xff0c;也叫prompt 用途&#xff1a;让Midjourney生成对应图片&#xff08;符合提示词所描述内容的图片&#xff09;&#xff0c;控制图片生成方向种类&#xff1a;文本提示、图像提示、参数提示&#xff0…

    【论文阅读】RAG-Reward: Optimizing RAG with Reward Modeling and RLHF

    研究背景 研究问题&#xff1a;这篇文章要解决的问题是如何优化检索增强生成&#xff08;RAG&#xff09;系统&#xff0c;特别是通过奖励建模和人类反馈强化学习&#xff08;RLHF&#xff09;来提高大型语言模型&#xff08;LLMs&#xff09;在RAG任务中的效果。研究难点&…

    《Trustzone/TEE/安全从入门到精通-标准版》

    CSDN学院课程连接:https://edu.csdn.net/course/detail/39573 讲师介绍 拥有 12 年手机安全、汽车安全、芯片安全开发经验,擅长 Trustzone/TEE/ 安全的设计与开发,对 ARM 架构的安全领域有着深入的研究和丰富的实践经验,能够将复杂的安全知识和处理器架构知识进行系统整…

    Pyecharts之地图图表的强大功能

    在数据可视化领域中&#xff0c;地图图表是一种强大的工具&#xff0c;能够直观地展现与地理位置相关的数据信息&#xff0c;帮助我们更好地洞察数据的地域特征和分布规律。Pyecharts 为我们提供了丰富的地图图表功能&#xff0c;让我们可以轻松实现各种地理信息的可视化展示。…

    政安晨的AI大模型训练实践三:熟悉一下LF训练模型的WebUI

    政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 目录 启动WebUI 微调模型 LLaMA-Factory 支持通过 WebUI 零代码微调大语言模型。 启动Web…

    【2024年华为OD机试】(A卷,200分)- 创建二叉树 (JavaScriptJava PythonC/C++)

    一、问题描述 构建二叉树并返回根节点 题目描述 请按下列描述构建一颗二叉树,并返回该树的根节点: 先创建值为-1的根结点,根节点在第0层;然后根据operations依次添加节点:operations[i] = [height, index] 表示对第 height 层的第 index 个节点 node,添加值为 i 的子节…

    有限元分析学习——Anasys Workbanch第一阶段_终篇_齿轮整体强度案例分析

    目录 0 序言 1 齿轮整体强度分析案例 1.1 模型简化 1.2 前处理 1&#xff09;分析类型选择 2&#xff09;设置平面参数 3&#xff09;约束、载荷及接触 2 控制网格 a.初次生成网格&#xff0c;对局部网格不做控制 b.第一次调整接触网格&#xff0c;接触面网格控制为…