首先咱们要知道在ES6以前JS是没有块级做用域的。那时只能经过函数来建立局部做用域,那么做用域究竟是什么呢?首先咱们须要了解的是做用域作什么的?当JavaScript引擎在某一做用域中碰见变量和函数的时候,须要可以明确变量和函数所对应的值是什么,因此就须要做用域来对变量和函数进行查找,而且还须要肯定当前代码是否对该变量具备访问权限。说白了所谓做用域,就是变量或者是函数能做用的范围。bash
那么JavaScript中有哪些做用域呢?函数
咱们所定义的除了函数里的变量之外的全部变量都在全局做用域内。this
var str ="hello world"
var arr =[1,2,3]
var obj ={name:"cxk"}
var a=1;
function f(){
var b=2;
}
复制代码
上面定义的全部变量只有b不在全局做用域里,由于b被定义在f函数内,与此同时b所在的做用域就叫作局部做用域。spa
ES6以后出现了let和const能够定义变量,而它们所定义的变量就存在着块级做用域。prototype
let a=1;
}
consloe.log(a)
复制代码
运行代码会报错:a is not defined 代码中的{}就是一个因为let定义变量而造成的块级做用域,a这个变量只有在{}中才能访问。3d
变量随着做用长辈函数一级一级往上搜索,直到找到为止,找不到就报错,这个过程就是做用域链起的做用。咱们也能够从执行上下文这个角度来理解做用域链这个概念。code
function Outer(){
var outer = 'outer';
Inner();
function Inner(){
var inner = 'inner';
console.log(outer,inner) // outer inner
}
}
复制代码
当咱们调用Inner函数时它会在本身的函数执行上下文找outer和inner变量,结果只找到了inner。那么这时它就去本身的父函数Outer中找outer变量,找到了就返回给Inner函数。因此这种逐级去本身的父函数的执行上下文中搜索变量的方式就是做用域链。orm
在JavaScript中一切皆对象,那么函数也是一个对象。因此这函数里也有不少属性,这其中必然有一个prototype
属性 cdn
var Person = function(name){
this.name = name;
}
Person.prototype.say = function(){
console.log( this.name)
};
var person = new Person('cxk');
person.say();//cxk
复制代码
上面的例子中,对象person是new Person建立的实例,在使用new操做符调用函数时主要执行如下几个步骤:对象
1,建立新的对象,并将函数的this指向新建立的对象
2,执行函数
3,返回新建立的对象
4,将本身的__proto__(隐式原型对象)指向构造函数的原型对象
与此同时原型对象中的constructor也指向了构造器
因为原型对象也是一个对象,因此它也有一个__proto__指向它的构造器Object,一样的Object也有一个__proto__指向Null。
因此当咱们想使用对象的某些方法时例如obj.a()
会先到本身的__proto__对象中找,若是没有就会去它的原型对象的原型对象中找,也就是__proto__.proto 。以此类推...
至此做用域链和原型链介绍完了,若有错误还望指正,谢谢。