JavaScript Function中你可能不知道的知识点
目录
函数的声明
函数的属性与特性
函数作用域
函数参数的传递方式
arguments 对象
闭包
函数是一段可以反复调用的代码块。函数还能接受输入的参数,不同的参数会返回不同的值。
函数的声明
- function命令
function print(s) {console.log(s);
}
- 函数表达式
var print = function(s) {console.log(s);
};
- Function 构造函数
var add = new Function('x','y','return x + y'
);// 等同于
function add(x, y) {return x + y;
}
你可以传递任意数量的参数给Function
构造函数,只有最后一个参数会被当做函数体,如果只有一个参数,该参数就是函数体。
函数的属性与特性
- name属性
函数的name
属性返回函数的名字。
function f1() {}
f1.name // "f1"// 如果是通过变量赋值定义的函数,那么name属性返回变量名。
var f2 = function () {};
f2.name // "f2"
- leng属性
函数的length
属性返回函数预期传入的参数个数,即函数定义之中的参数个数。
function f(a, b) {}
f.length // 2
不管调用时传入多少个参数,leng属性值始终等于2,length
属性就是定义时的参数个数,与调用无关。
- 函数名提升
JavaScript 引擎将函数名视同变量名,所以采用function
命令声明函数时,整个函数会像变量声明一样,被提升到代码头部。所以,下面的代码不会报错。
f();function f() {}
函数作用域
作用域分全局作用域 和 函数作用域,全局作用域,变量在整个程序中一直存在,所有地方都可以读取;函数作用域,变量只在函数内部存在。
- 在函数内部定义的变量,外部无法读取,称为“局部变量”。
function f(){var v = 1;
}v // ReferenceError: v is not defined
- 函数内部定义的变量,会在该作用域内覆盖同名全局变量。
var v = 1;function f(){var v = 2;console.log(v);
}f() // 2
v // 1
- 函数作用域内部也会产生“变量提升”现象。
var
命令声明的变量,不管在什么位置,变量声明都会被提升到函数体的头部 - 函数本身也是一个值,也有自己的作用域。就是其声明时所在的作用域,与其运行时所在的作用域无关(与调用无关)。
var a = 1;
var x = function () {console.log(a);
};function f() {var a = 2;x();
}f() // 1// 函数执行时所在的作用域,是定义时的作用域,而不是调用时所在的作用域。
var x = function () {console.log(a);
};function y(f) {var a = 2;f();
}y(x)
// ReferenceError: a is not defined// 同样的,函数体内部声明的函数,作用域绑定函数体内部。
function foo() {var x = 1;function bar() {console.log(x);}return bar;
}var x = 2;
var f = foo();
f() // 1
函数参数的传递方式
- 函数参数如果是原始类型的值(数值、字符串、布尔值),传递方式是传值传递
这意味着,在函数体内修改参数值,不会影响到函数外部。
var p = 2;function f(p) {p = 3;
}
f(p);p // 2
- 函数参数是复合类型的值(数组、对象、其他函数),传递方式是传址传递。
也就是说,传入函数的原始值的地址,因此在函数内部修改参数,将会影响到原始值。
var obj = { p: 1 };function f(o) {o.p = 2;
}
f(obj);obj.p // 2
如果函数内部修改的,不是参数对象的某个属性,而是替换掉整个参数,这时不会影响到原始值。
var obj = [1, 2, 3];function f(o) {o = [2, 3, 4];
}
f(obj);obj // [1, 2, 3]
这是因为,形式参数(o
)的值实际是参数obj
的地址,重新对o
赋值导致o
指向另一个地址,保存在原地址上的值当然不受影响。
就是说 o 其实作为参数代表数组 [1,2,3] 的地址,又被赋予了 [2,3,4] 的地址,所以不会影响到 obj。
arguments 对象
- 由于 JavaScript 允许函数有不定数目的参数,所以需要一种机制,可以在函数体内部读取所有参数。这就是
arguments
对象的由来。
arguments
对象包含了函数运行时的所有参数,arguments[0]
就是第一个参数,arguments[1]
就是第二个参数,以此类推。这个对象只有在函数体内部,才可以使用。
- 虽然
arguments
很像数组,但它是一个对象。数组专有的方法(比如slice
和forEach
),不能在arguments
对象上直接使用。 arguments
对象带有一个callee
属性,返回它所对应的原函数。
var f = function () {console.log(arguments.callee === f);
}f() // true
闭包
理解闭包,首先必须理解变量作用域。前面提到,JavaScript 有两种作用域:全局作用域和函数作用域。函数内部可以直接读取全局变量。但是函数外部无法读取函数内部声明的变量。出于种种原因,需要得到函数内的局部变量。正常情况下,这是办不到的,只有通过变通方法才能实现。那就是在函数的内部,再定义一个函数。
function f1() {var n = 999;function f2() {console.log(n);}return f2;
}var result = f1();
result(); // 999
上面代码中,函数f1
的返回值就是函数f2
,由于f2
可以读取f1
的内部变量,所以就可以在外部获得f1
的内部变量了。
闭包就是函数f2,
由于在 JavaScript 语言中,只有函数内部的子函数才能读取内部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。
闭包的最大用处用两个:
- 可以读取外层函数内部的变量
- 让外层函数的变量始终保持在内存中
为什么闭包能够返回外层函数的内部变量:
闭包用到了外层变量,导致外层函数不能从内存释放。只要闭包没有被垃圾回收机制清除,外层函数提供的运行环境也不会被清除,它的内部变量就始终保存着当前值,供闭包读取。
JavaScript Function中你可能不知道的知识点相关推荐
- JAVA SE中你可能不知道的知识点
一.你可以给数字添加下划线 例如1_000_000(或者0b1111_0100_0010_0100_0000)表示100万.下划线阅读起来更容易,JAVA编译器会直接删除他们 二.带标签的break声 ...
- 国际计算机思维比赛,少儿编程领域中,你所不知道的国际计算思维大赛
原标题:少儿编程领域中,你所不知道的国际计算思维大赛 孩子学习编程,除了培养编程思维和计算思维,也能为未来应对人工智能时代打下基础.今天给大家讲的的是Bebras国际计算思维大赛,请大家持续关注坚果学 ...
- java function void_Java8中你可能不知道的一些地方之函数式接口实战
什么时候可以使用 Lambda?通常 Lambda 表达式是用在函数式接口上使用的.从 Java8 开始引入了函数式接口,其说明比较简单:函数式接口(Functional Interface)就是一个 ...
- jmeter中控制器其中一个访问不到_Jmeter你所不知道的知识点!
测试片段是什么 应用在控制器上的一个特殊线程组,与线程组处于同一层级,必须与Include Controller或模块控制器一起使用才被执行. 应用场景 1.当jmeter脚本非常复杂的时候,可以通过 ...
- mysql时间字段中又t和z怎么处理_Mysql 中现在仍旧不知道的小知识点
重点: 表结构的增删改: alter table t_students add id int; alter table t_students drop id; alter table t_studen ...
- 前端见微知著JavaScript基础篇:你所不知道的apply, call 和 bind
在我的职业生涯中,很早就已经开始使用JavaScript进行项目开发了.但是一直都是把重心放在了后端开发方面,前端方面鲜有涉及.所以造成的一个现象就是:目前的前端知识水平,应付一般的项目已然是足够的, ...
- CSS3 Transitions 你可能不知道的知识点
如何临时让transition失效 我们给一个element设置了transition效果,但某些特殊情况,我们希望让transition临时失效. 我们第一反应就是先移除transition设置,等 ...
- cmake字符串转数组_JS 数组中你或许不知道的操作
JS 中的 Array ecma-262 中的定义:Array 对象是一种特殊对象,它会对数组索引属性键进行特殊处理. 每个 Array 对象都有一个不可配置的 length 属性,其最大值是 2³² ...
- java8中class怎么用_Java8中你可能不知道的一些地方之方法引用实战
Java8 中引入方法引用新特性,用于简化应用对象方法的调用, 方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法. 方法引用提供了一种引用而不执行方法的方式,它需要由兼容的函数式接口构成的 ...
最新文章
- OpenCV访问Mat图像中每个像素的值
- BZOJ3476 : [Usaco2014 Mar]The Lazy Cow
- 一些用过的优秀软件摘录
- python线性回归算法简介_Python实现的简单线性回归算法实例分析
- c ++查找字符串_C ++类和对象| 查找输出程序| 套装4
- matlab图像增强分段线性函数_图像增强、锐化,利用 PythonOpenCV 来实现 4 种方法!...
- 微课|中学生可以这样学Python(例11.4):tkinter版图片查看器
- 怎么单选_听力三个选项都出的单选怎么破?| 附今日听力S1S2及听力原文
- 稳住 稳住 。不要急!
- 【基础教程】基于matlab GUI界面介绍与搭建【含Matlab源码 189期】
- 总线外设基础1——i2s,i2c,uart,spi,touchpanel,lcd
- 布线问题分支界限法求解
- SM2椭圆曲线公钥密码算法
- 雷特智能家居龙海祁:从专业调光到全宅智能,20年专注成就专业
- 性能测试---如何确定最大并发用户数
- 微信小程序源码案例大全
- 【VUE】【高德地图】如何隐藏(去除)高德地图api左下角logo
- 敦煌莫高窟唐代离婚协议书曝光 用词浪漫煽情
- 支持幻灯片演示的思维导图软件NovaMind_我是亲民_新浪博客
- 与iOS的初吻---方法命名与调用
热门文章
- 领导驾驶舱如何助力领导做决策?
- Android开发的参考书籍和参考网站
- linux sda sda1区别,linux – / dev / sda和/ dev / sda1之间的区别
- s5pv210_gpio驱动及其在android2.3.1下jni调用
- php mysql弹幕_PHP开发弹幕系统
- 今年诺贝尔奖得主居然把这事研究清楚了:学历和收入到底有多大关系?
- 精通python自然语言处理pdf_学习NLP《自然语言处理综论第2版》中文PDF+英文PDF+对比分析...
- 压力传感器与数据采集
- Base58原理及代码
- 第一课:QT Quick项目架构说明