在js中作用域 有 全局作用域 局部作用域 還有一個es6的 塊級作用域
1.全局作用域 一般定義在 全局中 在任何地方都可以使用
var a=10; 全局作用域
console.log(a); //輸出 10
console.log(window.a); // 輸出 10
function zuoyong(){
console.log(a)
}
zuoyong(); // 輸出10
{
console.log(a); // 輸出 10
}
2.局部作用域 一般使我們在函數內部定義的變量 所在的作用域
function fn(){
var a=10;
console.log(a);
}
fn(); // 輸出 10
console.log(a); // 全局作用域中並沒有定義a 所以報錯 a is not defined
- 塊級作用域則是 es6 新增的 唯有使用 let 和const 關鍵字生效的 這個就不一一贅述了
我之前的博客 let 和const關鍵字 中有詳細講解
https://blog.csdn.net/yunchong_zhao/article/details/105894891
作用域鏈
講解這個 就避不開 js的一座大山 閉包的相關知識
面試經常被問到的一個問題就是 你在工作中哪裏會用到閉包
保證this 上下文一致的 使外層函數的this 作用到內層函數。
閉包 作爲菜鳥的我的理解就是 內層函數的 引用外層函數的作用域 導致無法在內存中釋放,這個 作用域就可以叫做閉包 。
很經典的一個例子就是累加器的實現
function sum(){
var sum=0;
return function(){
return ++sum;
}
}
var fn3=sum();
console.log(fn3());
console.log(fn3());
console.log(fn3());
console.log(fn3());
console.log(fn3());
console.log(fn3());
而上面的這個例子無形之中就已經牽扯出來了作用域鏈了
內層的那個function 裏面是沒有sum 這個變量的 所以它就會沿着作用域鏈 往外層尋找
看見了外層函數 sum 有一個 sum變量 他就引用到了
這裏之所以沒有釋放掉 可以看出後面幾個函數的執行結果是在前面的結果之上進行了加1
和js的垃圾回收機制 有關 1. 標記清楚 2.引用計數
我們再看看一個例子 可能就明白了
var a=10;
function sum(){
var sum=0;
return function(){
console.log(a);
}
}
var func=sum();
func(); // 輸出 10
這個相當於了三層 內層函數=>外層函數=>全局作用域
這個就是一個作用域鏈 和原型鏈有點類似 在當前作用域中找不到 就沿着作用域鏈往上面找
這裏也附上一個只是點 牽扯作用域 很敏感的一個 關鍵字 就是 this 關鍵字
function func(){
console.log(this===window)
}
func(); //true this 一般指向當前的作用域
其中箭頭函數中可沒有this
var obj={
name:"zhangsan",
say:function(){
console.log(this.name)
}
}
obj.say(); // zhangsan
// 改成箭頭函數 這裏爲什麼不用name 在window中 name好像是一個保留字吧
var obj={
a:"zhangsan",
say:()=>{
console.log(this.a,this==window)
}
}
obj.say(); // undefined true
很奇怪是把 this 箭頭函數中的this 最後竟然指向了 window
就是我在上面說了 箭頭函數中沒有 this 作用域 他就會沿着往上面找 自然就找到了 全局中的window 作用域了 主要是這個例子 只是套了兩層 如果三層的話他會指向第二層的this
指向window一般就是一經找到了 作用域鏈的最高層了 不能再往上面走了
在舉一個例子 下面的這個是不加new的
window.name="123";
function Person(name,age){
this.name=name;
this.age=age;
return ()=>{
console.log(this.name);
}
}
var app=Person("zhangsan",15);
app(); // zhangsan
var Fn=()=>{
return function(){
console.log(this.name)
}
}
Fn()(); // zhangsan
還有一個是加new的
window.name="123";
function Person(name,age){
this.name=name;
this.age=age;
return ()=>{
console.log(this.name);
}
}
var app=new Person("zhangsan",15);
app(); // 輸出 zhangsan
var Fn=()=>{
return function(){
console.log(this.name)
}
}
Fn()();// 輸出 123