JS函数易错点及难点学习记录
2020-06-05 05:31
70 查看
文章目录
1. 作用域
作用域: function声明时的作用域,所以函数参数的取值范围为函数本身所在的作用域
var a = 1; var x = function () { console.log(a); }; function f() { var a = 2; x(); } f() // 1
2. 闭包
2.1 概念理解
衍生概念: 闭包 >> 定义在一个函数内部的函数:
- 当函数外部想要调用函数(f1)内部的局部变量,可以在函数内部定义一个子函数(f2),子函数可以使用父函数的局部变量,如果将子函数返回,就可以在外部使用局部变量 --链式作用域结构
- f2即为闭包
function f1() { var n = 999; function f2() { console.log(n); } return f2; } var result = f1(); result(); // 999
2.2 状态保留
外部调用局部变量依赖于闭包,也就是闭包的诞生环境(函数),所以,外部调用结束之前函数会一直存在于内存里
函数调用的过程中,局部变量一直存在,且保留
function increment(start) { //start局部变量 return function () { return start++;// start += 1局部变量改变 }; } var inc = increment(5); inc() // 5 inc() // 6 inc() // 7
2.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
2.4 缺点
外层函数的每次运行都会产生一个新的闭包,并且闭包中保存外层函数的内部变量,根据上文中提到的状态保留,内存消耗大,影响网页性能
3. 参数
多个参数: 传的参数少于参数列表个数时,忽略后面的参数;同名参数,取后者
function f(a, a) { console.log(a); } f(1) // undefined //同名参数取后者,因为只有一个参数,第二个参数被忽略,所以undefined
4. 函数提升
JS将函数名视为变量名function f(){}会被函数提升
var f = function () { console.log('1'); } function f() { console.log('2'); } f() // 1 ;后者函数提升,后声明函数覆盖先声明的同名函数,所以结果为1
赋值逻辑不会被提升
console.log(a); console.log(b); var a; var b = 1; undefined // a被变量提升 undefined // b被变量提升,但是赋值不会被提升 f(); var f = function (){}; // TypeError: undefined is not a function;赋值不被提升
5. 立即调用函数表达式(IIFE)
Immediately-Invoked Function Expression
在 JavaScript 中,圆括号()
是一种运算符,跟在函数名之后,表示调用该函数。比如,
print()就表示调用
// 语句 function f() {} // 表达式 var f = function f() {}
- JavaScript 引擎规定,如果
function
关键字出现在行首,一律解释成语句 - 不让
function
出现在行首,则解释为表达式
(function(){ /* code */ }()); // 或者 (function(){ /* code */ })();
通常情况下,只对匿名函数使用这种“立即执行的函数表达式”。它的目的有两个:一是不必为函数命名,避免了污染全局变量;二是 IIFE 内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量。
6. eval命令
eval 以独立存在有意义的字符串为参数,并执行,否则报错
eval的作用域为当前作用域,所以会造成变量污染; 严格模式下eval内部声明的变量不会影响外部作用域,但依然可以访问外部作用域的变量.依然会有安全风险
(function f() { 'use strict';//使用严格模式 eval('var foo = 123'); console.log(foo); // ReferenceError: foo is not defined })()
(function f() { 'use strict'; var foo = 1; eval('foo = 2'); console.log(foo); // 2 })()
eval的参数如果不是字符串,则原样返回
eval(123);//123
eval的别名调用作用域为全局作用域,即使在函数内部,依然为全局作用域
6.1 应用场景
从服务器动态获取代码来执行;可能会有被攻击者通过eval代码注入导致风险
感谢补充与修改建议
参考链接:
函数提升
eval不是魔鬼
Javascript教程
JS严格模式
相关文章推荐
- JavaScript学习记录总结(四)——js函数的特殊性
- 廖雪峰JS教程学习记录----学习函数
- js学习记录2--匿名函数,函数参数
- JavaScript学习记录总结(六)——js函数闭包特性
- css+js 学习记录
- sql cast,convert,QUOTENAME,exec 函数学习记录
- v8学习---添加有返回值的js全局函数
- 数据库学习:oracle的递归写法,分析函数写法,以及teradata的取一定数量记录的写法
- destoon学习记录(一)--支持中文的字符串切割函数
- v8学习---添加js全局函数
- JavaScript高级程序设计(第2版) 学习笔记:(一)js函数依赖性
- sql cast,convert,QUOTENAME,exec 函数学习记录
- JS函数的原型及对象,对象方法,对象属性的学习
- js记录 数学函数、字符串函数API
- js 学习 函数
- js学习之函数声明与函数表达式区别[原创]
- js回调,apply,call 函数学习
- Three.js学习记录--html5的编辑和第一个场景
- Node.js学习笔记(3)——关于回调函数和函数的回调
- 【记录】JS正则表达式的相关方法(正则学习笔记1)