摘要:构造函数调用会使用新创建的对象作为调用上下文。函数的参数相关可选形参当传入的实参比函数声明时指定的形参数量要少,剩下的形参都将设置为值实参多则会自动省略。它们的第一个实参是要调用函数的母对象,它是调用上下文,函数体内通过引用它。
写在前面
注:这个系列是本人对js知识的一些梳理,其中不少内容来自书籍:Javascript高级程序设计第三版和JavaScript权威指南第六版,感谢它们的作者和译者。有发现什么问题的,欢迎留言指出。
1.函数声明和函数表达式函数声明具有声明提前/声明提升的特性,这一点和变量的声明特性相似,执行代码之前会先读取函数声明和变量声明,意味着可以把函数声明放在调用它的语句后面,但变量声明肯定最好不要这样,因为常伴随undefined问题。
函数声明的函数名称和函数体都提前,而函数表达式只是变量声明提前(而变量的初始化代码仍然在原来的位置)。
2.函数调用构成函数主体的代码定义时并不会执行,调用函数时才会执行,有4中方式调用函数:
作为函数
作为方法
作为构造函数
通过call()和apply()方法间接调用
①作为函数调用的注意点,严格模式下调用上下文是undefined,所以通常不使用this关键字,②作为方法调用的话调用上下文就是方法所在的对象,this关键字引用着该对象。③而嵌套函数不会从调用它的函数中继承this,如果想访问外部的this,可以用变量保存this的值。④构造函数调用会使用新创建的对象作为调用上下文。
3.函数的参数相关可选形参
当传入的实参比函数声明时指定的形参数量要少,剩下的形参都将设置为undefined值(实参多则会自动省略)。所以在合适的场景就可以选择使用可选形参:
function getPropertyNames(o, /* optional */ a) { if(a=== undefined) a=[]; for(var prop in o) a.push(prop); return a; } var arr = [1,2]; //[1, 2, "x", "y"] console.log(getPropertyNames({x:1,y:2},arr)); //["x", "y"] console.log(getPropertyNames({x:1,y:2}));
注意点:需要将可选形参放在形参列表的最后,并在函数定义是使用注释强调形参是可选的。
实参对象arguments
在函数体内,标识符arguments是指向实参对象的引用,它是一个类数组对象,可以通过数字下标访问传入的实参值,这样函数就可以操作任意数量的实参:
function getMaxValue(/* ... */) { var max = arguments[0]; for(var i=0,len=arguments.length;imax){ max = arguments[i]; } } return max; } console.log(getMaxValue(4,2,1,8,10));//10
将对象属性用作实参:当一个函数的形参过多(比如超过3个),调用时记住实参的正确顺序不容易。这时可以把形参写成一个对象,就没有参数顺序的影响了,而且还可以在取值的时候使用||符号设置默认值。当然,形参不多就不需这样做,效率会低一些。
在每个形参左边使用类似/*array*/的类型注释。在函数体内应该要有实参类型检查的逻辑,在传入非法值时报错。
自定义函数属性:函数是一种特殊的对象,所以在适当的时候可以给函数定义属性,比如函数需要一个“静态变量”:
//阶乘 function factorial(n) { if(isFinite(n) && n>0 && n==Math.round(n)){ if(!(n in factorial)) factorial[n] = n * factorial(n-1); return factorial[n]; } else return NaN; } factorial[1] = 1; console.log(factorial([5]));//1204.作为命名空间的函数
为了不污染全局空间,常用定义匿名函数并立即在单个表达式中调用的方式:
var extendFun = (function () { //函数体 }());5.call()、apply()和bind()
call()和apply()
call()和apply()是函数的方法,通过调用方法的形式来简介调用函数,我们之前介绍继承的时候,有一个地方是借用超类型的构造函数,就是使用了call。它们的第一个实参是要调用函数的母对象,它是调用上下文,函数体内通过this引用它。
call除了第一个参数之后的参数就是要传给函数的值:
function logMsg(x,y,z) { console.log(x+"/"+y+"/"+z); } //打印2/4/6 logMsg.call({},2,4,6);
而apply除了第一个参数以外,提供一个数组用于传给函数:
function logMsg(x,y,z) { console.log(x+"/"+y+"/"+z); } //打印8/10/12 logMsg.apply({},[8,10,12]);
apply的数组参数可以是真实数组,也可以是类数组对象,比如可以把当前函数的arguments数组直接传入:
function logMsg(x,y,z) { console.log(x+"/"+y+"/"+z); } function wantToLog(a,b,c) { logMsg.apply({},arguments); } //打印1/2/3/4 wantToLog(1,2,3);
bind()
这个方法主要作用是将函数绑定至某个对象,除了第一个实参以外,其他的实参会传入到函数里面:
function f(y,z) { console.log("y:"+y);//y:4 console.log("z:"+z);//z:2 return this.x + y + z; } var g = f.bind({x:3},4); console.log(g(2));//3+4+2=9 //这里面绑定了this和y
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/108389.html
摘要:在此例中,在匿名函数被返回后,它的作用域链初始化为包含函数的活动对象和全局变量对象。函数在执行完毕后,其活动对象也不会被销毁,因为匿名函数的作用域链仍然在引用这个活动对象,结果就是只是的执行环境的作用域链会被销毁,其活动对象会留在内存中。 写在前面 注:这个系列是本人对js知识的一些梳理,其中不少内容来自书籍:Javascript高级程序设计第三版和JavaScript权威指南第六版,...
摘要:写在前面正在看的源码看到了部分感觉以前看的正则表达式基础知识已经完全不够用了现翻阅博客资料将一些中正则表达式难用的部分总结归纳方便自己和友翻阅正则分组重复匹配对于重复的匹配我们经常使用到正则表达式的分组功能我们使用正则匹配地址来实践一下假 [TOC] 写在前面 - Lionad 正在看VueJS的源码, 看到了HtmlParser部分, 感觉以前看的正则表达式基础知识已经完全不够用了,...
摘要:返回后,代表操作已完成,记录结束时间并输出。从零组装因为对的学习和使用,知道了自己对于后台框架的真实需求。所以这回决定不用之内的工具,而是自己从零开始,组装一个适合自己的框架。就是去和上,寻找一个一个的包并组装在一起了而已。 起因 作为一个前端,Node.js算是必备知识之一。同时因为自己需要做一些后台性的工作,或者完成一个小型应用。所以学习了Node的Express框架,用于辅助和加...
摘要:好程序员前端培训入门之基础知识梳理汇总,前端工程师是当前各大企业都比较稀缺的人才,薪资待遇和就业前景都很不错。作用域链的前端,始终是当前执行代码所在环境的变量对象。 好程序员Web前端培训入门之JS基础知识梳理汇总,Web前端工程师是当前各大企业都比较稀缺的人才,薪资待遇和就业前景都很不错。不论是专业还是非专业,有基础亦或是无基础,都想通过学习Web前端实现高薪就业。不过,学习要一...
摘要:好程序员前端培训入门之基础知识梳理汇总,前端工程师是当前各大企业都比较稀缺的人才,薪资待遇和就业前景都很不错。作用域链的前端,始终是当前执行代码所在环境的变量对象。 好程序员Web前端培训入门之JS基础知识梳理汇总,Web前端工程师是当前各大企业都比较稀缺的人才,薪资待遇和就业前景都很不错。不论是专业还是非专业,有基础亦或是无基础,都想通过学习Web前端实现高薪就业。不过,学习要一...
阅读 4482·2021-10-13 09:39
阅读 1813·2019-08-29 11:12
阅读 1057·2019-08-28 18:16
阅读 1798·2019-08-26 12:16
阅读 1179·2019-08-26 12:13
阅读 2930·2019-08-26 10:59
阅读 2196·2019-08-23 18:27
阅读 2921·2019-08-23 18:02