JS函数深入
函数的本质是对象
三种定义方式
1、 字面量=function声明
function add() {
// body...
}
add();
2、 var赋值表达式
var add = function (argument) {
// body...
};
add();
var add = function fn(argument) {
// body...
fn();
add();
};
add();
fn();//会报错,只能在函数体内调用
3、 构造函数
var add = new Function('num1', 'num2', 'return num1 + num2;');
add();
三种定义方式区别:
字面量=function声明:预加载时add=function
console.log(add());
function add() {
return 1;
}
var赋值表达式:预加载时add=undefined
console.log(add());
var add = function () {
return 1;
};
构造函数:少用
杂七杂八的知识点:
JS中没有块级作用域,所以不会在if中发生预解析,在外部预解析的时候,if中声明的所有函数都会被提前,所以无法达到按需定义的目的。
内部函数可以访问外部函数的变量(作用域链的机制)
案例:写出一个加法(add)函数,并在其内部定义一个函数(isNumber),用来判断add的参数是否可以转化为数字类型进行相加,
如果可以,就在页面中输出结果;
如果不能就退出add,给出提示“请传入数字类型的参数”
function add(num1,num2){
if(isNaN(num1) || isNaN(num2)){
alert('请传入数字类型的参数');
return;
}else{
return parseInt(num1)+parseInt(num2);
}
}
var num1=prompt('请输入数字1');
var num2=prompt('请输入数字2');
alert(add(num1,num2));
案例:匿名函数也是函数,当它自执行的时候会创建函数作用域,它里面的变量和函数都是局部的,当匿名函数执行完毕后会被销毁。所以我们在外面访问不到add
function () {
function add(num1,num2){
return num1+num2;
}
}();
document.write(add(1,2));//报错
匿名函数自执行方式:
var add = function () {
console.log(1);
}();
(function () {
console.log(1);
})();
!+-~function () {
console.log(1);
}();
递归调用:递归调用就是自己调用自己,但切记一定要有终止条件,否则函数将无限递归下去
function factorial(num) {
if (num <= 1) return 1;
return num * factorial(num - 1);
// return 5 * 4! = 5 * 4 * 3! =... 5 * 4 * 1!
}
console.log(factorial(5));
方法的调用:
document.onclick = function () {
console.log('你点击了文档!');
};
document.onclick();
var operation = {
add: function (num1, num2) {
return num1 + num2;
},
subtract: function (num1, num2) {
return num1 - num2;
},
'@': function () {
console.log('@');
},
key: function () {
// body...
}
};
console.log(operation.add(1, 2));
console.log(operation['@'](1, 2)); //@符比较特别
var key = 'add';
console.log(operation[key](1, 2));
链式调用
var operation = {
add: function (num1, num2) {
console.log(num1 + num2);
return this;
},
subtract: function (num1, num2) {
console.log(num1 - num2);
return this;
},
'@': function () {
console.log('@');
},
key: function () {
// body...
}
};
operation.add(1, 2).subtract(2, 1);
间接调用:
对象没有call和apply方法,只有函数有
call和apply的唯一区别就在它们传参的方式上
apply可以将数组和类数组一次性的传递进函数中,call只能一个一个的传;
var name = 'xm';
var person = {};
person.name = 'xh';
person.getName = function () {
return this.name;
};
console.log(person.getName()); //this指向person
console.log(person.getName.call(window)); //this指向window
console.log(person.getName.apply(window)); //this指向window function add(num1, num2) {
return num1 + num2;
}
console.log(add(1, 2));
var datas = [1, 2];
console.log(add.call(window, 1, 2));
console.log(add.apply(window, datas)); //apply(ele,[])

输出:'xm', [object Object]
person()就是普通函数的调用,返回值是return后面的内容:'xm' ; new person()是将person作为构造函数调用,返回的永远是对象 ; document.write没法输出对象,它会尝试着将其转换成字符串输出

输出:undefined
call可以改变函数中this的指向,这里在调用方法的时候将其this改为了window,所以this.value就变成了window.value,而window.value没有定义过,所以为undefined
函数的参数:
function add() {
if (arguments.length == 0) return;
var sum = 0;
for (var i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
return sum;
}
console.log(add());
console.log(add(1, 2, 3, 4, 5));
arguments
类数组,实质是类
function fn(name) {
arguments[0] = '';
console.log(name);
}
fn('xm');//没有输出
arguments.callee 指代函数本身,多用于递归
计算阶乘方法一:
function factorial(num) {
if (num <= 1) return 1;
return num * factorial(num - 1);
}
console.log(factorial(5));
计算阶乘方法二:
function factorial(num) {
if (num <= 1) return 1;
return num * arguments.callee(num - 1);
}
console.log(jiecheng(5));
计算阶乘方法三:
var jicheng = function fn(num) {
if (num <= 1) return 1;
return num * fn(num - 1);
};
console.log(jicheng(5));
判断传入实参的个数是否与形参相等
arguments.length实参个数
add.length形参个数
function add(num1, num2) {
if (arguments.length != add.length) throw new Error('请传入' + add.length + '个参数!');
return num1 + num2;
}
console.log(add(1, 1));
console.log(add(1));
console.log(add(1, 2, 3));
案例:

输出:1,1,1,1,2,3
1、 count()()这样调用,每次都会创建一个新的局部作用域,num的值会不断地被初始化为1
2、 return num++表示先返回num的值,再将num加1
3、 先将count()赋给fn,此时count()只调用了一次,接下来多次调用fn()的时候,count函数并没有多次调用,num只会在count函数调用的时候被初始化,所以多次调用fn()的时候num不会被多次初始化;由于fn相当于count函数的内层函数(var fn=count();这行代码执行后,就调用了count(),调用count后就将里面的函数赋值给了fn,所以说fn就相当于函数的内层函数了。),可以访问count中的变量num,所以多次调用fn函数,会将num的值累加;
JS函数深入的更多相关文章
- 3.3 js函数
1.函数语法: 函数声明的方式:function 函数名(参数1,参数2-){//函数体;}函数调用:函数名(参数1,参数2-); 函数内不一定都指定返回值. 如果需要指定返回值,可用 return ...
- Js函数function基础理解
正文:我们知道,在js中,函数实际上是一个对象,每个函数都是Function类型的实例,并且都与其他引用类型一样具有属性和方法.因此,函数名实际上是指向函数对象的指针,不与某个函数绑定.在常见的两种定 ...
- js函数表达式和函数声明的区别
我们已经知道,在任意代码片段外部添加包装函数,可以将内部的变量和函数定义"隐 藏"起来,外部作用域无法访问包装函数内部的任何内容. 例如: var a = 2; function ...
- 通用js函数集锦<来源于网络> 【二】
通用js函数集锦<来源于网络> [二] 1.数组方法集2.cookie方法集3.url方法集4.正则表达式方法集5.字符串方法集6.加密方法集7.日期方法集8.浏览器检测方法集9.json ...
- 通用js函数集锦<来源于网络/自己> 【一】
通用js函数集锦<来源于网络/自己>[一] 1.返回一个全地址2.cookie3.验证用户浏览器是否是微信浏览器4.验证用户浏览器是否是微博内置浏览器5.query string6.验证用 ...
- 100多个基础常用JS函数和语法集合大全
网站特效离不开脚本,javascript是最常用的脚本语言,我们归纳一下常用的基础函数和语法: 1.输出语句:document.write(""); 2.JS中的注释为//3.传统 ...
- JS函数
1.document.write(""); 输出语句2.JS中的注释为//3.传统的HTML文档顺序是:document->html->(head,body)4.一个浏 ...
- js函数和运算符
函数是由事件驱动或者它被调用时执行可重复使用的代码块. <script> function myFunction(){ Alert(“hello World!”): } </scri ...
- JavaScript学习03 JS函数
JavaScript学习03 JS函数 函数就是包裹在花括号中的代码块,前面使用了关键词function: function functionName() { 这里是要执行的代码 } 函数参数 函数的 ...
- JSF页面中使用js函数回调后台bean方法并获取返回值的方法
由于primefaces在国内使用的并不是太多,因此,国内对jsf做系统.详细的介绍的资料很少,即使有一些资料,也仅仅是对国外资料的简单翻译或者是仅仅讲表面现象(皮毛而已),它们的语句甚至还是错误的, ...
随机推荐
- HDU_5602_概率dp
http://acm.hdu.edu.cn/showproblem.php?pid=5602 dp[1][i][j]表示轮到第二个人操作时,第一人总和i,第二人总和j,第一人胜的最小概率(因为每个人都 ...
- HTML5与HTML4的区别-----文档结构
HTML5在结构和语法上做了大量的简化.当然,也提供了语义化的标签 结构上区别: 1.简化了文档声明语句 HTML5仅规定了一种: <!DOCTYPE html> 2. ...
- EIP
EIP中的值就是CPU下次要执行的地址 jmp 直接修改eip的值 1.jmp imm=mov eip,imm 2.jmp r 3.jmp m call 直接修改eip的值,并把当前指令的下一行地址存 ...
- css 纯css轮播图 示例
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
- pytorch之 CNN
# library # standard library import os # third-party library import torch import torch.nn as nn impo ...
- 网站windows可以访问mac和linux无法访问【MTU MSS问题】
环境: 阿里云LB 内网地址类型,代理后面的k8s上的服务 公司和阿里云之间vpn打通 在windows上进行访问一切正常,在相同的办公局域网linux主机内访问不通,mac笔记本访问同样不通,tel ...
- python os和sys模块使用
python os和sys模块使用 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 os.chdir("dirname") 改变当前脚本工作目录:相 ...
- Linux 发行版本简述
在撰写这篇文章前,先向linux创始人 Linus Torvalds 先生致敬,感谢您二十多年前的无私开源! 其次向二十多年来维护更新的开发者们致敬! Lin ...
- 手把手带你阅读Mybatis源码(三)缓存篇
前言 大家好,这一篇文章是MyBatis系列的最后一篇文章,前面两篇文章:手把手带你阅读Mybatis源码(一)构造篇 和 手把手带你阅读Mybatis源码(二)执行篇,主要说明了MyBatis是如何 ...
- 一个故事看懂Linux文件权限管理
前情回顾: 我通过open这个系统调用虫洞来到了内核空间,又在老爷爷的指点下来到了sys_open的地盘,即将开始打开文件的工作. 详情参见:内核地址空间大冒险:系统调用 open系统调用链 我是一个 ...