函数的本质是对象

三种定义方式

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函数深入的更多相关文章

  1. 3.3 js函数

    1.函数语法: 函数声明的方式:function 函数名(参数1,参数2-){//函数体;}函数调用:函数名(参数1,参数2-); 函数内不一定都指定返回值. 如果需要指定返回值,可用 return ...

  2. Js函数function基础理解

    正文:我们知道,在js中,函数实际上是一个对象,每个函数都是Function类型的实例,并且都与其他引用类型一样具有属性和方法.因此,函数名实际上是指向函数对象的指针,不与某个函数绑定.在常见的两种定 ...

  3. js函数表达式和函数声明的区别

    我们已经知道,在任意代码片段外部添加包装函数,可以将内部的变量和函数定义"隐 藏"起来,外部作用域无法访问包装函数内部的任何内容. 例如: var a = 2; function ...

  4. 通用js函数集锦<来源于网络> 【二】

    通用js函数集锦<来源于网络> [二] 1.数组方法集2.cookie方法集3.url方法集4.正则表达式方法集5.字符串方法集6.加密方法集7.日期方法集8.浏览器检测方法集9.json ...

  5. 通用js函数集锦<来源于网络/自己> 【一】

    通用js函数集锦<来源于网络/自己>[一] 1.返回一个全地址2.cookie3.验证用户浏览器是否是微信浏览器4.验证用户浏览器是否是微博内置浏览器5.query string6.验证用 ...

  6. 100多个基础常用JS函数和语法集合大全

    网站特效离不开脚本,javascript是最常用的脚本语言,我们归纳一下常用的基础函数和语法: 1.输出语句:document.write(""); 2.JS中的注释为//3.传统 ...

  7. JS函数

    1.document.write(""); 输出语句2.JS中的注释为//3.传统的HTML文档顺序是:document->html->(head,body)4.一个浏 ...

  8. js函数和运算符

    函数是由事件驱动或者它被调用时执行可重复使用的代码块. <script> function myFunction(){ Alert(“hello World!”): } </scri ...

  9. JavaScript学习03 JS函数

    JavaScript学习03 JS函数 函数就是包裹在花括号中的代码块,前面使用了关键词function: function functionName() { 这里是要执行的代码 } 函数参数 函数的 ...

  10. JSF页面中使用js函数回调后台bean方法并获取返回值的方法

    由于primefaces在国内使用的并不是太多,因此,国内对jsf做系统.详细的介绍的资料很少,即使有一些资料,也仅仅是对国外资料的简单翻译或者是仅仅讲表面现象(皮毛而已),它们的语句甚至还是错误的, ...

随机推荐

  1. [转载]goldendict下优质词典简介及安装

    使用Arch Linux一年以来,如果要问自己最为中意的词典程序是? 当然是Goldendict啦!想详细了解这款瑞士军刀的请猛戳这里. 以前在Win下都是用的lingoes, 感觉还不错,词典库很全 ...

  2. 51Nod 1021 石子归并(区间dp经典入门)

    题意: N堆石子摆成一条线.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的代价.计算将N堆石子合并成一堆的最小代价. n<=100 思 ...

  3. 这个 Spring 循环依赖的坑,90% 以上的人都不知道

    1. 前言 这两天工作遇到了一个挺有意思的Spring循环依赖的问题,但是这个和以往遇到的循环依赖问题都不太一样,隐藏的相当隐蔽,网络上也很少看到有其他人遇到类似的问题.这里权且称他非典型Spring ...

  4. 5G为人工智能与工业互联网赋能 高清79页PPT

    人工智能和5G是时下最热门的科技领域之一,两者都是能改变社会,推进下一代工业革命的颠覆性技术. 工业互联网是利用基础科学.工业.信息技术.互联网等领域的综合优势,从大数据应用等软服务切入,注重软件.网 ...

  5. MongoDB、Redis和Memcached介绍

    MongoDB MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非 ...

  6. Go语言实现:【剑指offer】字符流中第一个不重复的字符

    该题目来源于牛客网<剑指offer>专题. 请实现一个函数用来找出字符流中第一个只出现一次的字符.例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是 ...

  7. JAVA ReentrantLock的使用

    源码如下 对比synchronized,synchronized使用时会显示的指定一个对象(方法为调用对象,代码块会需要对象作为参数),来获取一个对象的独占锁 而ReentrantLock可能就是使用 ...

  8. 今天第一天开通博客,随笔总结一下resultType(属性)和resultMap,collection和association,Statement和PreparedStatement各自的区别

    1.resultType(属性)和resultMap(标签引用)的区别? resultType不支持自定义返回结果,会将查询到的结果通过到type中java对象的同名的属性,对象中的属性名必须和数据库 ...

  9. windows10 CTCP

    windows上除了普通tcp之外,有一个CTCP. 据说可以提升长延时情况下的吞吐量. win7可以方便的通过netsh int tcp set global congestionprovider= ...

  10. 杭电-------2047阿牛的eof牛肉串(C语言写)

    /* 主要看最后一个是否为O,若为O,则倒数第二个不能为O,则为a[n-2]*1*2; 若不为O,则最后一个有两个选择则为a[n-1]*2 */ #include<stdio.h> ] = ...