javascript函数总结

这篇博客是关于javascript函数中的内容的总结。
一、函数名 函数名就相当于一个指针
可以使用函数名.name来获取函数名

<script>function sum(a, b) {console.log(a + b);}let func = sum;sum = null;  //将函数的指针设置为空 func(1,2);// ①普通函数的函数名function sum(a,b){return a+b;}console.log(sum.name);// ②、箭头函数的函数名let obj = () =>{};console.log(obj.name);// ③空箭头函数的函数名console.log((()=>{}).name); //这里是空字符串// ④、当使用new Function()进行实例化对象的时候,let obj = new Function();console.log(obj.name);  //一个匿名函数// ⑤、如果函数是获取函数,或者设置函数,以及bind()实例化,那么标志符前面会加一个前缀function sum(){console.log(this);}console.log(sum.bind(null).name);  //bound sumlet obj={years:20,set age(newAge){this.years = newAge;},get age(){return this.years;}}let desc = Object.getOwnPropertyDescriptor(obj,'age');console.log(desc.get.name);  //get ageconsole.log(desc.set.name);  //set age
</script>

注意: 对象中的获取函数和设置函数,必须使用 Object.getOwnPropertyDescriptor来进行设置
二、理解函数中的参数问题
①在函数中参数可以传入是没有限制的,最终会在arguments对象中进行展现,但是传入参数的地址和arguments中的地址是不相同的,可以使用arguments[0]…来表示相应的参数,并且可以存在双向绑定的问题。

<script>function some(num1,num2){console.log(arguments[0]);console.log(arguments[1]);console.log(num1);console.log(num2);num1 =10;console.log(arguments[0]);arguments[0] = 100;console.log(num1);}some(1,2,3);
</script>

②、箭头函数的参数是不能使用arguments关键字进行访问的。

<script>function foo(){console.log(arguments[0]);}foo(5);//下面的报错let bar = ()=>{console.log(arguments[0]);};bar(3)
//    此时可以在普通函数内部显示,因为这个argument来自最外面一层传入的参数
function sum(){let bar = ()=>{console.log(arguments[0]);};bar()}sum(1);
</script>

③arguments只接收传入的参数,如果没有传入参数,则显示undefined

<script>function set(name){name = "foo";console.log(arguments[0]);}set();   //undefined
</script>

三、就是的重载问题
首先什么是重载
在定义函数中,如果存在两个函数同名,当调用函数时,会根据你所调用函数的变量类型以及变量的个数来确定执行哪个函数,但是js中没有重载,因为arguments对象。

<script>
// ①、这样相当于覆盖function sum(num1) {console.log(num1 + 100);}function sum(num1){console.log(num1 + 200);}sum(100);
// ②、下面就相当于指针指向改变var obj = function (num1) {console.log(num1 + 100);}var obj = function (num1) {console.log(num1 + 200);}obj(100);
</script>

四、默认参数

<script>// 这里在ES5中可以判断是否传入参数function set(name){name = (typeof name !== 'undefined')?name:"dl";console.log(name);}set();set("xsy")// 在ES6中可以显示添加参数function set(name = "dl"){console.log(name);}set("xsy")// 默认参数的作用域以及暂时性死区
function set(name = "dl",age = name){console.log(name);console.log(age);}set()// ②函数的形参不能将函数内部的参数作为形参function set(name = "dl", age = sex){sex = "男";console.log(name,age,sex);}set();//报错// ③、箭头函数也是一样可以使用默认形参let obj = (name ="dl")=>{console.log(name);}obj();
</script>

五、参数扩展与收集

<script>// 一、扩展运算符  这里类似于结构let values = [1, 2, 3, 4];function getSum() {let sum = 0;for (let i = 0; i < arguments.length; i++) {sum += arguments[i];}return sum;}console.log(getSum(values));  //01,2,3,4console.log(getSum.apply(null,values));  //10;console.log(getSum(...values));  //10console.log(getSum(-1,...values));  //9console.log(getSum(...values,10));  //20console.log(getSum(...values,...[10,20,30]));  //70
</script>
<script>// 也可以使用默认的参数let values = [1,2,3];function getSum(a,b,c=1){return a+b+c;}console.log(getSum(...values));</script>
<script>// 二、收集参数  就是扩展反过来function getSum(...values){return values.reduce((x,y)=>x+y,0);}console.log(getSum(1,2,3));function getSum(...values){console.log(values);console.log(arguments.length);}getSum(1,2,3);
</script>

六、函数声明和函数表达式// 存在函数提升

<script>
//这里显示正确console.log(sum(1,2));function sum(num1,num2){return num1+num2;}// 函数表达式,这里显示报错console.log(sum(1,2));let sum = function(num1, num2){return num1+num2;}
</script>

七、函数作为参数传入

<script>function add10(num1) {return num1 + 10;}function create(func,some){return func(some);}console.log(create(add10,10));
</script>
<script>let arr = [1,3,4,5,67];let arr_1 = arr.sort(function(x,y){return x-y;})console.log(arr_1);
</script>
函数作为返回值输出
<script>function createCompare(property){return function(object_1,object_2){let value_1 = object_1[property];let value_2 = object_2[property];if(value_1>value_2){return 1;}else if(value_1 <value_2){return 2;}else{return 0;}}}let obj = [{name:"dl",age:30},{name:"xsy",age:20},]let arr_1 = obj.sort(createCompare("age"));console.log(arr_1);
</script>

八、函数内部
①、 arguments.callee指向arguments所在的函数

<script>function factor(num) {if (num <= 1) {return 1;} else {return num * factor(num - 1);}}let obj = factor(3);console.log(obj);
</script>
<script>// 下面是使用arguments.callee()进行解耦let factor = function(num){if (num <= 1) {return 1;} else {return num * arguments.callee(num - 1);}}let some = factor;factor=function(){return  0;}let obj = factor(3);console.log(obj);let obj_1 =some(3);console.log(obj_1);</script>

解析:上面两个都是同一个例子,只是下面采用了arguments.callee来降低耦合度
九、函数中this的指向
①、在普通函数中的this指向window,并且函数名是将函数的地址存在在其中,也可以说函数名是函数的指针

<script>var color = "red";function sayColor(){console.log(this.color);}sayColor();
</script>

②、普通函数的this指向执行对象

<script>let o={name:"dl"}      o.sayColor=function(){console.log(this.name);}o.sayColor();
</script>

③、因为箭头函数没有this,所以箭头函数中的this只能来源于外部

<script>window.color = "red"let obj = () => {console.log(this.color);}obj();
</script>

④、对象中的箭头函数

<script>let o ={color:"red"}o.sayColor =()=>{console.log(this);}o.sayColor();// 这里指向window
</script>

⑤、匿名函数的this指向window

<script>window.color= "red";function king(){setTimeout(function(){console.log(this.color);},1000)}king();
</script>

⑥、匿名函数如果是箭头函数

<script>window.color= "green";function king(){this.color="red";setTimeout(()=>{console.log(this.color);})}king();
</script>

箭头函数中的this继承上层的this,并且箭头函数不能在arguments和super以及new.target中使用,并且箭头函数中没有prototype属性
this的使用

<script>window.name = "dl"let obj = {name:"xsy",getName(){return function(){return this.name;}}}console.log(obj.getName()());  //这里是匿名函数,匿名阿函数的this在非严格模式下指向window对象// 在严格模式下显示undefined
</script>

十、 caller的使用
函数名.caller表示该函数的调用者

<script>function outer(){inner();}function inner(){console.log(inner.caller);}outer();// 为了降低耦合性 使用arguments.callee.caller;function outer(){inner();}function inner(){console.log(arguments.callee.caller);console.log(arguments.caller);   //undefind}outer();   // 改变的方法window.name = "dl"let obj = {name:"xsy",getName(){let that = this;return function(){return that.name;}}}console.log(obj.getName()());// 改变的方法二、window.name = "dl"let obj = {name: "xsy",getName() {let that = this;return ()=>{return this.name}}}console.log(obj.getName()());  //这里是因为在箭头函数中this指向上层的this// 下面一个例子window.name = "张三";let object = {name:"李四",getName(){return this.name;}}console.log(object.getName());   //李四   正常的闭包console.log((object.getName)());   //李四console.log((object.getName = object.getName)());  //张三  这是因为对object.getName进行赋值操作,右边的Object.getName()就是一个函数,this值不再与任何对象绑定,所以指向window对象</script>

十一、函数中的new.Target

<script>// 在函数中可以使用new关键字来定义,也可以直接定义function hans(){if(!new.target){console.log("请使用new关键字来定义");}else{console.log('请不用new关键字来执行函数');}}hans();new hans()</script>

十二、函数的属性和方法
函数中的属性

<script>// length属性可以查找传入的参数个数//name属性可以输出名字function sum(){console.log(sum.name);console.log(sum.length);}sum();console.log(sum.prototype);
</script>

函数中的方法

call()
<script>window.color = "red"let o={color:"green"}function some() {console.log(this.color);}some(); //redsome.call(this);  //redsome.call(o);// call的传值  传入一个一个的参数function some(num1, num2,num3) {sum.call(null,num1,num2,num3)}function sum(a, b, c) {console.log(a + b + c);}some(1,2,3);
</script>
apply()函数
<script>function add(){sum.apply(null,arguments);}function sum(a,b,c){console.log(a+b+c);}add(1,2,3);function add(num1,num2,num3){sum.apply(null,[num1,num2,num3]);}function sum(a,b,c){console.log(a+b+c);}add(1,2,3);
</script>
<script>// bind()函数使用时,创建一个实例  也是单个单个的传入参数function sum(a,b,c){console.log(a+b+c);}let obj = sum.bind(null,2,3,4);obj();</script>
<script>// toString方法就是打印出函数function sum(){console.log("hhh");  //这里是注释}console.log(sum.toString());  //  toLocaleString()方法function sum(){console.log("hhh");  //这里是注释}console.log(sum.toLocaleString());  // valueOf()方法function sum(){console.log("hhh");  //这里是注释}console.log(sum.valueOf());
</script>

十三、函数表达式 两种方式

<script>sayHello();function sayHello(){console.log("Helloween");}sayHello();// 函数表达式obj(); //报错,let obj = function(){  //匿名函数console.log("你好");}obj();  </script>

// 函数声明的其他例子

<script>// 不能这样声明let comm = false;if(comm){function sayHello(){console.log("hello");}}else{function saySorry(){console.log("sorry");}}// sayHello();saySorry();// 可以使用函数表达式进行声明定义let comm = true;if(comm){var saySorry=function(){console.log("sorry");}}else{var sayHello =function(){console.log("hello");}}// sayHello();saySorry();
</script>

十四、函数递归

<script>function comm(num) {if (num <= 1) {return 1;} else {return num * arguments.callee(num - 1);}}console.log(comm(3));// 在严格模式下,可能会出错,所以可以使用函数表达式const fact = (function f(num){if(num <=1){return 1;}else{return num * f(num-1);}})console.log(fact(10));
</script>

十五、尾调用优化
在函数执行中,需要开辟一个栈空间,如果在该函数中仍然存在另一个函数,所以仍然会占用栈空间的情况。当需要执行的操作过多的情况,则会出现栈溢出的情况。使用尾调用优化操作可以解决这一个问题:下一个执行函数的返回的值就是本次函数的返回值,所以可以将本次的操作先弹出,然后再将下次的操作进行进栈操作。

<script>// 递归的尾调用优化function some(num) {console.log(num);if (num <= 1) {return num;}return some(num - 1);}some(100);
</script>
<script>// 非递归的尾调用优化function some(num1,num2){return add(num1,num2);}function add(num1,num2){return num1+num2;}console.log(some(1,2));</script>
<script>//斐波那契数列的尾调用优化和非尾调用优化function feb(n) {if (n < 2) {return n;} else {return feb(n - 1) + feb(n - 2);}}console.log(feb(10));//这里由于存在return后面是+,所以这是非尾调用优化// 斐波那契数列尾调用优化function ferb(a,b,n){if(n<2){return a;}else{return ferb(b,a+b,n-1);}}console.log(ferb(1,1,10));</script>

十六、闭包
能够读取其他函数内部变量的函数叫做闭包函数

<script>function sum(){let n =1;return function(){console.log(n++);}}// 下面显示两个1sum()();sum()();// 这里显示1,2let a = sum();a();a();
</script>

两次不一样的原因:因为之前的sum()()后引用次数为0,所以导致这一次函数执行完毕之后,就会立即销毁。但是在下面的例子中,使用a来引用,所以函数执行完毕后不会立即销毁,所以由于作用域链,所以前面的n也不会销毁。

<script>function some(){let n = 1;return function(){console.log(n++);let m = 10;return function(){console.log(m++);}}}let b = some();b()();b()();b()();
// 解析:这里的和前面的一样,但是不能销毁
let c= some();let d = c();d();d();d();c()();c()();
</script>

这里将some()函数赋值给b,并且立即执行b,以及立即执行b函数中返回的函数,但是里面的函数没有被引用。所以执行之后,就会被销毁。

<script>// 构造函数function some(){let n = 1;this.say=function(){console.log(n++);}}let a = new some();a.say();a.say();let b = new some();b.say();b.say();// 构造函数每初始化实例,里面的数据都是可以保存的。
</script>

十七、块级作用域和函数作用域

<script>// let作用域,块级作用域for(var i=0;i<4;i++){console.log(i);}console.log(window.i);for(var i=0;i<4;i++){setTimeout(function(){console.log(i);},1000)}console.log(window.i);for(let i =0;i<3;i++){console.log(i);} </script>
<script>// var存在函数作用域,所以可以使用函数来解决for (var i = 0; i < 4; i++) {(function(a){setTimeout(function(){console.log(a);})})(i)}
</script>
<script>// 如果想要保存let定义i的作用域let arr = [];for(let i=0;i<5;i++){arr.push(function(){return i;})//这样通过在这个块级作用域中添加一个函数,增加这个函数的引用值,所以导致这个块级作用域不能被去除}console.log(arr[2]());
</script>
<script>// varlet arr = [];for(var i = 0;i<5;i++){(function(a){arr.push(function(){return a;})})(i)}console.log(arr[3]());
</script>

闭包的应用

<script>let arr = [21, 43, 65, 2, 6, 7, 10];function change(a, b) {return function (v) {return v >= a && v <= b;}}let arr_1 = arr.filter(change(10,50));console.log(arr_1);// 解释:传入两个参数的时候,返回一个函数,函数中进行对上面的变量进行比较,// 此时形成闭包,
</script>

闭包小demo

<script>//闭包小demo二//  根据闭包筛选价格let object = [{name: "dl",age: 19,}, {name: "xsy",age: 20}, {name: "sss",age: 111,}, {name: "wd",age: 9}]function change(a, b) {return function (v) {return v.age >= a && v.age <= b}}let arr_1 = object.filter(change(10,100));console.table(arr_1);
</script>

闭包案例

<script>function save(property){return function move(obj_1,obj_2){let value_1 = obj_1[property];let value_2 = obj_2[property];if(value_1>value_2){return 1;}else if(value_1<value_2){return -1;}else{return 0;}}}let vare = save("age");console.log(vare({age:20},{age:10}));vare = null;  //去除垃圾
</script>

十八、内存泄漏
如果我们在一个实例中只是需要某一个属性,并不需要其他的元素,或者属性值,此时如果还可以访问,就会造成内存泄漏问题。解决内存泄漏问题如下。

<script>let Btns = document.querySelectorAll("button");Btns.forEach(function(item){let inner = item.innerHTML;item.addEventListener('click',function(){console.log(inner);console.log(item);})item = null;})
</script>

在最后将元素设置为null。
十九、私有变量
私有变量:就是在函数中单独定义的变量,在函数外部是不能被访问到的。

<script>function sum(num1,num2){let sum = num1+num2;console.log(sum);}    sum(1,2);// 在这里num1和num2以及sum都是私有变量
</script>
<script>// 私有变量不能在外部获取,一般我们可以利用闭包来获取function Change(){let value = 10;   //这里注意需要let声明this.sayValue = function(){return value;  //这里注意没有this}}let obj = new Change();console.log(obj.sayValue());
</script>
<script>// 利用闭包获取和更改私有变量function Change(name){this.getValue =function(){return name;},this.setValue = function(newValue){name = newValue;}}let obj_1 = new Change("xsy");console.log(obj_1.getValue());obj_1.setValue("dl");console.log(obj_1.getValue());// 静态私有变量:就是将变量设置在构造函数的原型上(function(){let name = "";Person = function(value){name = value;}Person.prototype.getName = function(){return name;},Person.prototype.setName = function(value){name = value;}})();let person_1 = new Person("xsy");console.log(person_1.getName());person_1.setName("dl")console.log(person_1.getName());
</script>

二十、javascript模块模式
模块模式就是在一个函数中如果存在私有变量和私有函数,可以采用模块模式让其导出。采用这种模式我们可以保护私有变量。

<script>
//  一、导出私有变量和方法let some = function (name) {return {name:name,}}console.log(some("dl").name);
</script>

模块增强模式

<script>//模块增强模式//在返回之前对对象进行增强function Case(name) {this.name=name;}Case.prototype.sayHello=function(){console.log("hewllo");}let obj= (function(){let age =20;let object = new Case();object.publicCase = true;object.publicMethod = function(){return age++;}return object})();console.log(obj.publicMethod());
</script>

模块模式demo

<script>let object = (function () {let arr = [];return {addObject(value) {arr.push(value);console.log(arr);},getAllthing() {return arr.length;},}})();object.addObject({ name: "javascript高级程序设计", price: 200 });object.addObject({ name: "计算机网络", price: 89 });console.log(object.getAllthing());
</script>

javascript函数总结相关推荐

  1. 深入理解javascript函数系列第二篇——函数参数

    前面的话 javascript函数的参数与大多数其他语言的函数的参数有所不同.函数不介意传递进来多少个参数,也不在乎传进来的参数是什么数据类型,甚至可以不传参数.本文是深入理解javascript函数 ...

  2. 怎样在javascript函数中将变量传递给服务端脚本程序?

    怎样在javascript函数中将变量传递给服务端脚本程序? (有朋友问上述问题, 愿把结论分享给大家). 摘 要:   服务器端脚本运行时, 它只会解释执行<% %>或<?php ...

  3. 史上自定义 JavaScript 函数Top 10

    史上自定义 JavaScript 函数Top 10 http://www.dustindiaz.com/top-ten-javascript/     发布:wpulog | 发布时间: 2010年4 ...

  4. HTML和JavaScript函数之间的关系

    在javaScript中有两类函数,一个是自定义的函数,一个是JavaScript中的函数.在HTML中javaSrcipt能和HTML完全的融合,也就是我们的JavaScript系统函数能直接的应用 ...

  5. python 调用 javascript函数

    python 调用 javascript函数 # pip install pyexecjs import execjs # 直接执行 print('execjs.eval:', execjs.eval ...

  6. 现代 JavaScript 函数库 usuallyjs 的安装和使用

    usuallyjs usuallyjs 是一个面向现代 Web 开发的 JavaScript 实用函数库. usuallyjs 基于 ES6 开发,抛弃了传统 Web 开发中 DOM 和 BOM 操作 ...

  7. Javascript函数执行、new机制以及继承

    JS函数执行 一个JavaScript函数fn,被执行有三种途径: fn() new fn() fn.call()或fn.apply() new机制以及继承 JavaScript中定义了一种对象,称之 ...

  8. Javascript函数的简单学习

    第九课 函数的定义与调用 1:函数的定义     语法格式     function 函数名(数据类型 参数1){//function是定义函数的关键字         方法体;//statement ...

  9. 主页面调用iframe里面匿名Javascript函数的问题

    2019独角兽企业重金招聘Python工程师标准>>> 这个问题出现已经几天了,今天终于解决了,特此记录下来. 问题的出现始于我在HTML5下采用Reveal.js来播放PPT和使用 ...

  10. javascript函数作用域与闭包

    8.8. 函数作用域与闭包        如第四章所述,JavaScript函数的函数体在局部作用域中执行,局部作用域不同于全局作用域.本章将解释这些内容和相关的作用域问题,包括闭包.[*] [*] ...

最新文章

  1. Matlab中plot基本用法
  2. PG git pull
  3. Collection和Collections区别
  4. c mysql 地址池_FreeRadius 根据mysql 下发指定地址池的地址...
  5. 【JS逆向百例】某音乐网分离式 webpack 非 IIFE 改写实战
  6. linux nmap下载教程,Linux_在Linux系统上用nmap扫描SSL漏洞的方法,以下载nmap 6.45及以上版本。如 - phpStudy...
  7. IOleItemContainer的接口定义
  8. 2016去哪儿编程题:字符替换
  9. 图解TCP 的重传、滑动窗口、流量控制和拥塞控制机制
  10. 闭包/私有化变量方法
  11. server多笔记录拼接字符串 sql_前台传入多个参数(数组格式),拼接成字符串中间用逗号隔开,传入到sql中用in查询....
  12. JavaScript中this指针指向的彻底理解
  13. c语言变量声明举例,C语言变量的定义和声明
  14. [原创]HierarchyView的实现原理和Android设备无法使用HierarchyView的解决方法
  15. 冰点还原精灵使用教程
  16. HTML炫彩按钮,Button - 动画按钮
  17. 机器学习之One-Hot Encoding详解
  18. hourglass论文_论文笔记 Stacked Hourglass Networks for Human Pose Estimation
  19. 怎么在PDF上修改文字,PDF修改文字的步骤
  20. android图片下载到本地

热门文章

  1. LWIP-TCP Server连接两次之后无法连接问题
  2. 单模光电转换器怎么接_光纤收发器怎么连接?光纤收发器连接图解!
  3. python 怎么打印数组_?怎么将python中的数组全部打印出来array
  4. 嵌入式分享合集128
  5. 【毕业设计_课程设计】位置信息管理网站设计(源码+论文)
  6. 利用Aria2和旧电脑打造一台下载机
  7. STM32F411核心板固件库开发(二) USART配置
  8. dojo是什么与选择dojo的理由
  9. np.random.normal()的含义及实例
  10. 你要知道的测试面试题