作用域
作者:互联网
变量提升
在代码执行之前,会先进行代码的预解析,将var和function声明的变量进行提升,提升为window的属性(全局变量),并将var声明的变量赋值为undefined,var的提升在function之前
console.log(num);
say();
var num = 100;
function say(){
console.log('hello');
}
console.log(num);
say();
变量提升
var num;
function say(){
consloe.log('hello');
}
console.log(num);//undefined
say();//'hello'
num = 100;
console.log(num);//100
say();//'hello'
变量名一致时会进行覆盖
console.log(num);
var num = 100;
console.log(num);
function num(){
console.log('20');
}
console.log(num);
var num = 50;
console.log(num);
变量提升
var num;
function num(){//覆盖原来的,此时num为一个函数
console.log('20');
}
console.log(num);//f num(){ console.log('20');}
num = 100;
console.log(num);//100
console.log(num);//100
num = 50;
console.log(num);//50
全局作用域
全局作用域是最大的作用域,指向window对象,在全局作用域内声明的变量,在JS代码的时时处处都可以访问
- 全局作用域是最外围的一个执行环境,在web浏览器中,全局执行环境被认为是window对象。
- 所有全局变量和函数都是作为window对象的属性和方法创建的。
- 全局变量拥有全局作用域,在javascript代码中的任何地方都是有定义的。
- 全局作用域直到应用程序退出例如关闭网页或浏览器时才会被销毁。
var num = 13;
function fn(){
console.log(num);
}
fn();//打印13
局部作用域
特点:函数作用域中的所有代码执行完毕后,该作用域被销毁,保存在其中的所有变量和函数定义也随之销毁。
function test(){
var message = 'hi';
}
test();
alert(message); // 报错
作用域链
- 全局作用域变量包括:全局变量(直接声明在全局中不在任何函数体中)成为window的属性、不使用var声明而直接赋值的变量
- 全局作用域直到应用程序退出例如关闭网页或浏览器时才会被销毁
- 局部变量:函数参数、函数内使用var声明的变量
- 函数调用产生局部作用域,函数调用完毕局部作用域销毁,保存在其中的所有变量和函数定义也随之销毁
- 内部作用域可访问外部作用域、外部作用域不可访问内部
- 函数局部作用域有与全局同名的变量,函数内部访问时,优先访问内部的
this
非严格模式下:
- 全局作用域中,this 指向window
- 函数里的this 指向函数的调用者 找不到调用者 就指向window对象
- 构造函数里的this 指向构造函数创建的对象实例
严格模式下:
- 全局作用域中,this指向window对象(与非严格模式一样)
- 全局作用域中函数中的this,指向undefined
- 对象的函数中的this指向调用函数的对象实例(与非严格模式一样)
- 构造函数中的this指向构造函数创建的对象实例(与非严格模式一样)
对象
对象的this指向该对象
function fm() {
console.log( this.a );
}
var obj = {
a: 2,
fn: fm
};
obj.fn(); //2
函数
函数的this指向调用者,对象调用指向对象,没有调用指向window
function fm() {
console.log( this.a );
}
var obj = {
a: 2,
fn: fm
};
obj.fn(); //2
fn();//undefined
改变this指向
call
fn.call(obj, param1,...) 隐式帮我们调用函数
参数:
obj fn内部的this指向的对象
从第二个参数开始,都是传递给fn函数的实参
var a = 89;
var obj = { a: 999 };
function fn(a, b) {
console.log(this.a);
return a + b;
}
var res1 = fn(100, 300);
var res2 = fn.call(obj, 100, 300);
console.log(res1 == res2);
apply
fn.apply(obj, [param1,param2...]) 隐式帮我们调用函数
参数:
obj fn内部的this指向的对象
第二个参数是一个数组,数组的每一个元素都会被当作实参传递给fn
var a = 89;
var obj = { a: 999 };
function fn(a, b) {
console.log(this.a);
return a + b;
}
var res3 = fn.apply(obj, [100, 300]); // fn(100, 300)
console.log(res3); // 400
bind
fn.bind(obj, param1,...) 不会隐式帮我们调用函数 返回一个函数的引用地址
参数:
obj fn内部的this指向的对象
从第二个参数开始,都是传递给fn函数的实参
注意:如果想bind的同时调用函数 就要()在后面表示函数的调用
var a = 89;
var obj = { a: 999 };
function fn(a, b) {
console.log(this.a);
return a + b;
}
var res4 = fn.bind(obj, 100, 300);
console.log(res4()); // 400
var res5 = fn.bind(obj, 100, 300)();
console.log(res5); // 400
var res6 = fn.bind(obj)(100, 300);
console.log(res6); // 400
区别
执行:
- call/apply改变了函数的this上下文后马上执行该函数
- bind则是返回改变了上下文后的函数,不执行该函数
返回值:
- call/apply 返回
fun
的执行结果 - bind返回fun的拷贝,并指定了fun的this指向,保存了fun的参数。
标签:console,log,作用域,num,var,fn 来源: https://www.cnblogs.com/Kongqingzhi/p/16608456.html