JS函数易错点及难点学习记录

1. 作用域

作用域: function声明时的作用域,所以函数参数的取值范围为函数本身所在的作用域

var a = 1;
var x = function () {
  console.log(a);
};

function f() {
  var a = 2;
  x();
}

f() // 1

2. 闭包

2.1 概念理解

衍生概念: 闭包 >> 定义在一个函数内部的函数:

  1. 当函数外部想要调用函数(f1)内部的局部变量,可以在函数内部定义一个子函数(f2),子函数可以使用父函数的局部变量,如果将子函数返回,就可以在外部使用局部变量 --链式作用域结构
  2. 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()就表示调用print函数。

// 语句
function f() {}

// 表达式
var f = function f() {}
  1. JavaScript 引擎规定,如果function关键字出现在行首,一律解释成语句
  2. 不让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严格模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值