js学习(4) 函数
JavaScript有三种声明函数的方法
(1)function命令
function print(s) {
console.log(s);
}
(2)函数表达式
1.var print = function(s) {
console.log(s);
};
2.var print = function x(){
console.log(typeof x);
};
x
// ReferenceError: x is not defined
print()
// function
3.var f = function f() {};
将匿名函数赋予变量,如果不匿名,也只在内部有效
函数表达式定义函数最后要加上分号代表结束
(3)Function构造函数
可以传递任意数量的参数给Function构造函数,但只有最后一个参数被当做函数体
Function构造函数可以不使用new命令,返回结果完全一样
var add = new Function(
'x',
'y',
'return x + y'
); // 等同于
function add(x, y) {
return x + y;
}
此方法比较不常用 第一种方法倒更熟悉
如果一个函数被多次声明,后面的声明就会覆盖前面的声明
调用函数时和其他语言大致相同,使用圆括号运算符
第一等公民
Js把函数看成一种值,与其他值(数值,字符串,布尔值等)地位相同
凡是可以使用值的地方,就能使用函数,函数只是一个可以执行的值
function add(x, y) {
return x + y;
}
// 将函数赋值给一个变量
var operator = add;
// 将函数作为参数和返回值
function a(op){
return op;
}
a(add)(1, 1)
// 2
函数提升
函数的属性和方法
name属性:返回函数名字 如果采用表达式定义函数,且function后有名字,则返回那个名字
length属性:返回函数预期传入的参数个数
toString():返回一个字符串,内容是函数的源码,以及注释
对于var命令来说,局部变量只能在函数内部声明,在其他区块中声明,一律都是全局变量
函数内部也有变量提升,var命令声明的对象,不管在什么位置,变量声明都会被提升到函数体的头部
函数本身的作用域
函数本身作用域就是声明时所在的作用域,与运行时所在作用域无关
在定义时绑定作用域
var a = 1;
var x = function () {
console.log(a);
}; function f() {
var a = 2;
x();
} f() // 1
函数的参数
可以省略,但没办法只省略靠前的参数,而保留靠后的参数,如果一定要省略靠前的参数,只有显式传入undefined
参数传递对原值的影响
如果是原始类型的值,无影响,只是一份拷贝
如果传入的是对象,则修改其属性的话,原值会受到影响
但把对象整个替换掉,不会影响原始值,因为相当于指向其他地址
同名参数
如果有同名参数,则取最后出现的那个值
function f(a, a) {
console.log(a); //a为最后一个a
}
f(1) // undefined 相当于f(1,undefined)
arguments对象
由于js允许函数提供不定数目的参数,所以需要一种机制,可以在函数体内部读取所有参数,这就是arguments对象的由来
arguments对象包含函数运行时所有参数,使用类似数组
如果在非严格模式下还可以在函数内部修改参数的值,严格模式下只读
通过它的length属性,可以判断函数调用时到底带了几个参数
与数组关系:
是对象,不能使用数组方法,除非转换为数组
var args = Array.prototype.slice.call(arguments); // 或者
var args = [];
for (var i = 0; i < arguments.length; i++) {
args.push(arguments[i]);
}
arguments自带一个callee属性1,返回它所对应的原函数,可以用这个写递归
arguments每个函数运行时都有,无需显式声明
函数的闭包
闭包即能够读取其他函数内部变量的函数,可以简单理解为“定义在一个函数内部的函数”
用处:1.读取函数内部变量 2.记住诞生的环境
function createIncrementor(start) {
return function () {
return start++;
};
}
var inc = createIncrementor(5);
inc() // 5
inc() // 6
inc() // 7
3.封装对象的私有属性和方法,感觉像类
function Person(name) {
var _age;
function setAge(n) {
_age = n;
}
function getAge() {
return _age;
}
return {
name: name,
getAge: getAge,
setAge: setAge
};
}
var p1 = Person('张三');
p1.setAge(25);
p1.getAge() // 25
立即调用的函数表达式,声明时就调用(IIFE)
(function(){ /* code */ }());
// 或者
(function(){ /* code */ })();
所以以下写法都行
var i = function(){ return 10; }();
true && function(){ /* code */ }();
0, function(){ /* code */ }();
!function () { /* code */ }();
~function () { /* code */ }();
-function () { /* code */ }();
+function () { /* code */ }();
通常只对匿名函数使用
目的:1.不必命名,避免污染全局变量 2。在IIFE内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量
eval命令
eval命令接受一个字符串作为参数,并将这个字符串当做语句执行
eval('var a = 1;');
a // 1
如果无法执行就报错
如果eval的参数不是字符串,那么会原样返回
eval的作用域是当前作用域,因此小心修改当前作用域变量的值
eval本质是在当前作用域中注入代码,由于安全风险和不利于js引擎优化执行速度,一般不推荐使用
最常用的场合是解析json数据的字符传递,不过正确做法应该使用原生的JSON.parse方法
js规定,凡是使用别名执行eval,eval内部一律是全局作用域
var a = 1;
function f() {
var a = 2;
var e = eval;
e('console.log(a)');
}
f() // 1
js学习(4) 函数的更多相关文章
- js学习之函数表达式及闭包
来自<javascript高级程序设计 第三版:作者Nicholas C. Zakas>的学习笔记(七) 直接切入主题~ 定义函数的方式有两种: 函数声明 function functio ...
- js学习之函数的参数传递
我们都知道在 ECMAScript 中,数据类型分为原始类型(又称值类型/基本类型)和引用类型(又称对象类型):这里我将按照这两种类型分别对函数进行传参,看一下到底发生了什么. 参数的理解 首先,我们 ...
- js学习之函数声明与函数表达式区别[原创]
作为一名js初学者,与大家分享下.Javascript中有函数声明提升的功能,会优先编译函数声明部分.比如, ff(); function ff(){ alert("hello world. ...
- js学习之函数
1/.js中函数就是对象. 2/以表达式方式定义的函数一般不要函数名以使代码紧凑. 3/js中函数声明的方式会被默认提到外部脚本或最前面,所以在其定义前的代码也可调用. 然而以表达式方式的则不行. 4 ...
- js学习笔记 -- 函数
js函数有类似javaMethod用法 Math.max.apply( Math.max.call( Array map,reduce,filter,sort , , , , , , , , ]; v ...
- JS学习之函数内部属性和方法
知识点:arguments和this对象.caller属性.apply()和call()方法 arguments对象:函数内部对象,传入函数中所有参数的集合,类数组对象 属性:callee 指 ...
- js学习-自定义函数、对象的字面量、json对象学习小结
一.自定义对象的构造: var student=new Object(); //object是顶级对象,使用构造函数的方法创建一个对象,此处的意思是创建了一个学生的空对象 student.name=& ...
- js学习:函数
概述 函数的声明 JavaScript 有三种声明函数的方法 function 命令 function命令声明的代码区块,就是一个函数.function命令后面是函数名,函数名后面是一对圆括号,里面是 ...
- node.js学习(2)函数
1 简答函数 2 匿名函数 3 回调函数
- JS学习之函数的属性和方法
随机推荐
- 巧妇难为无米之炊( Model数据)
一.相隔万里的客户端服务器数据交互 请求头发过去的轻量级文本数据,后台根据这些信息处理 response返回的如果时html的话,那么是全局刷新 在ajax中data回调获得了数据,然后操作dom进 ...
- Linux内核分析第三次作业
实验:mykernel时间片轮转多道程序内核 进入实验楼实验,在终端中分别输入以下命令 cd LinuxKernel/linux-3.9.4 rm -rf mykernel patch -p1 < ...
- @Transactional 可以写在 Controller 方法上面了
上图 t1 掉用的service 没定义事物环境,但是 在 t1 上面定义了. 依旧可以 在 参数是5 的 时候 ,让 前面的操作级联回滚. 但是 我不建议这么用,除非特殊需求,正常来说事物根据 ...
- 好久没考虑过的 sql 注入
很多年没考虑 sql 注入了,毕业以后 使用mybatis #{ 参数的 语法 },这个 语法已经 做了防止 sql 注入的处理 . 看到同事写的 ${ 参数 },突然 想到这个问题 . 下面聊聊 s ...
- Day 10 函数的形参,实参
今日内容 '''实参:调用函数,在括号内传入的实际值,值可以为常量.变量.表达式或三者的组合*****形参:定义函数,在括号内声明的变量名,用来接受外界传来的值''''''注:形参随着函数的调用 ...
- [转]Python依赖打包发布详细
Python依赖打包发布详细 http://www.cnblogs.com/mywolrd/p/4756005.html 将Python脚本打包成可执行文件 Python是一个脚本语言,被解释 ...
- jstack命令定位java程序CPU利用率高的代码位置
高手是怎么使用jstack精确找到异常代码的(java程序CPU利用率高的情况) 请jstack神器来帮忙 本文介绍Linux环境下使用jstack定位问题的秘笈1.[top命令]找到CPU利用率持续 ...
- STM32定时器时间的计算方法
本文出自:https://wenku.baidu.com/view/e3bdfb7601f69e31433294c4.htmlSTM32定时器时间的计算方法STM32中的定时器有很多用法:(一)系统时 ...
- ubuntu crontab python 定时任务备记
crontab -e 写入: # at a.m every week with: # * * tar -zcf /var/backups/home.tgz /home/ # # For more in ...
- Linux的命令技巧
一.使用apt-get installl 方法安装的库或者程序一般的路径如下 1.下载的软件存放位置 /var/cache/apt/archives 2.安装后软件默认位置 /usr ...