javascript面试必备知识(3)作用域和闭包

js面试必备知识,关注作者查看系列js知识体系

导语:作为一个程序员,要是作用域和闭包都没弄清楚,那将会是一个项目成员里面的核弹。

1,作用域

我们先来看一段代码,你觉得它们会输出什么?

var a = "123";
function test(){
 console.log(a);
 var a = "456";		//var a会预解析在函数开头,执行到这行才进行赋值
 console.log(a);
}
test();
console.log(a);		//"123" 找全局环境下的声明,找到了var a="123"

/*答案
undefined,
456.
123

函数执行后,在函数环境内发现有a,但是它在后面,就先对它初始化undefined。
接着就输出

*/
var a = "123";
function test(){
 console.log(a);
 a = "456";
}
test();
console.log(a);

/*答案
123
456
函数执行后,在函数环境内,没有找到本层环境关于a的声明,所以开始向上一层环境查找。
然后改变了全局变量a的内容。
*/
function test(){ 
 b();
 var a = 1;
 function b(){
  console.log(1);
  console.log(a);
  var a=2;
 }
}
test();

/*答案
1
undefined
*/

这些都是有迹可循的,先找本层环境有无声明,有的话,看是否进行了赋值;只有声明没有执行赋值,就是undefined。没有声明也没有赋值的话,就再向上一层查找,直到找到为止。如果所有的执行环境都没有找到,那么控制台就会报错变量找不到。

2,闭包

闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

主要有两种表现:函数作为参数被传递函数作为返回值被返回

function f1(){
  let a = 123
  function f2(){
    console.log(a)
  }
  return f2;
}
var f = f1();
let a = 456
f();	//123
let a = 100

function printf(fn) {
    let a = 200
    fn()
    console.log(a)
}
function fn() {
    console.log(a)
}
printf(fn) // 100 200

要记住一点,变量的查找要在函数定义的地方查找,查找不到才向上查找。

function fun(n,o) {
  console.log(o)
  return {
    fun:function(m){
      return fun(m,n);
    }
  };
}
var a = fun(0);  a.fun(1);  a.fun(2);  a.fun(3);//undefined,0,0,0
var b = fun(0).fun(1).fun(2).fun(3);//undefined,0,1,2
var c = fun(0).fun(1);  c.fun(2);  c.fun(3);//undefined,0,1,1

3,this

this的值是什么,是在函数执行的时候才知道的,而不是在定义的时候。

function fn() {
  console.log(this)
}
fn()						//window
fn1.call({ a: 1 })			//{a:1}
fn1.call(fn)				//fn
fn1.bind({ a: 1 })()		//{a:1}

4,call,bind,apply

它们都是劫持另外一个对象的方法,其中bind是返回一个方法(未执行),而call和apply都是返回一个执行的方法。不同的是apply传递的是一个数组。

/*定义一个人类*/  
function Person(name,age)  
{  
    this.name=name;  
    this.age=age;  
}  
/*定义一个学生类*/  
function Student(name,age,grade)  
{  
    Person.apply(this,arguments); //劫持person的方法,将参数传递过去
    console.log(this) 
    this.grade=grade;  
}  
//创建一个学生类  
var student=new Student("mi",21,"高一");  
console.log("name:"+student.name+"\n"+"age:"+student.age+"\n"+"grade:"+student.grade);

猜你喜欢

转载自blog.csdn.net/gitchatxiaomi/article/details/108030404
今日推荐