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做系统.详细的介绍的资料很少,即使有一些资料,也仅仅是对国外资料的简单翻译或者是仅仅讲表面现象(皮毛而已),它们的语句甚至还是错误的, ...
随机推荐
- Python中的hashable(散列)
Python文档中的解释: 一个对象是可散列的,那么在它的生命周期中它的hash 值是不变的. 可散列的对象需要2个方法:__hash__()方法和__eq__()方法.两个可散列的对象相等,那么它们 ...
- POJ_1182_并查集
http://poj.org/problem?id=1182 pre构建有关系的号码的树,rel保存当前号码与根的关系,0表示相同,1表示根吃当前,2表示当前吃根. 代码中的更新公式可以先把各种情况枚 ...
- CCF_ 201412-1_门禁系统
水. #include<iostream> #include<cstdio> using namespace std; int main() { ],num[] = {}; c ...
- HDU_2446_打表
http://acm.hdu.edu.cn/showproblem.php?pid=2446 打表,二分查找,注意查找最后的判断. #include<cstdio> #define N 2 ...
- 《N诺机试指南》(三)STL使用
1.vector 2.queue 3.stack 4.map 5.set 6.多组输入输出问题 详解见代码以及注释: //学习STL的使用 #include <bits/stdc++.h> ...
- UVA5913 Dictionary Sizes(字典树)(转载)
题目大意:给出n个旧单词,要从这n个旧单词中构造新单词.构造条件是 S = Sa + Sb,其中Sa为某个旧单词的非空前缀,Sb为某个单词的非空后缀.求所有的新单词和旧单词中有多少个不同的单词. 思路 ...
- eclipse里新建work set,将项目分组放在不同文件夹
想必大家的Eclipse里也会有这么多得工程...... 每次工作使用到的项目肯定不会太多...... 每次从这么大数量的工程当中找到自己要使用的, 必须大规模的滚动滚动条......有点不和谐了. ...
- vue路由核心要点(vue-router)
目录 目录 1.vue-router 是什么? 2.如何使用v-router? 3.vue-router跳转和传参 4.vue-router实现的原理 两种模式 5.vue-router 有哪几种导航 ...
- 在IDEA中如何使用lombok插件
lombok 插件 lombok是一款可以精减java代码.提升开发人员生产效率的辅助工具,利用注解在编译期自动生成 setter/getter/toString()/constructor之类的代码 ...
- 实验一 GIT 代码版本管理
实验一 GIT 代码版本管理 实验目的: 1)了解分布式分布式版本控制系统的核心机理: 2) 熟练掌握git的基本指令和分支管理指令: 实验内容: 1)安装git 2)初始配置git ,git ...