一、指针
1、指针的定义
this是当前函数/当前模块的运行环境的上下文, 是一个指针型变量, 可以理解为一个动态的对象, 普通函数中的this是在调用时才被绑定确认指向的。
2、this的绑定方式
(1)默认绑定
指函数独立调用的时候,不带任何修饰的函数引用。
- 非严格模式下 this 指向全局对象(浏览器下指向 Window,Node.js 环境是 Global )
- 严格模式会报错, Uncaught TypeError: Cannot read properties of undefined
(reading ‘a’)
var a = 'hello'
var obj = {
a: '你好',
foo: function() {
// 'use strict';
console.log(this.a)
}
}
var bar = obj.foo
bar() // hello
(2)隐式绑定
与默认绑定相反, 函数调用的时候有显式的修饰, 比如说某个对象调用的函数。
比如下面这段代码, foo 方法是作为对象的属性调用的,那么此时 foo 方法执行时,this 指向 obj 对象。
var a = 'hello'
var obj = {
a: '你好',
foo: function() {
onsole.log(this.a)
}
}
obj.foo(); // 你好
(3)显示绑定
- 通过函数call apply bind 可以修改函数this的指向(call 与 apply 方法都是挂载在 Function
原型下的方法,所有的函数都能使用)。 - call和bind函数接收的是一个参数列表,apply函数接收的是一个参数数组。
- bind 方法 会创建一个新函数。当这个新函数被调用时,bind() 的第一个参数将作为它运行时的this,之后的一序列参数将会在传递的实参前传入作为它的参数。
var person = { "name": "小明"};
function changeWork(company, work) {
this.company = company;
this.work = work;
};
changeWork.call(person, '字节', '前端');
console.log(person.work); // '前端'
changeWork.apply(person, ['腾讯', '后端']);
console.log(person.work); // '后端'
changeWork.bind(person, '阿里', 'CEO')();
console.log(person.work) // 'CEO'
(4)new绑定
function study(name){
this.name = name;
}
var studyDay = new study('李华');
console.log(studyDay); // {name: '李华'}
console.log(studyDay.name); // 李华
3、this绑定的优先级
new绑定 > 显式绑定 > 隐式绑定 > 默认绑定
二、闭包
1、概念
- 闭包是指那些能够访问自由变量的函数。
- 自由变量是指在函数中使用的,但既不是函数参数也不是函数局部变量的变量。
- 从理论角度:所有的函数都是闭包。因为它们都在创建的时候就将上层上下文的数据保存起来了。哪怕是简单的全局变量也是如此,因为函数中访问全局变量就相当于是在访问自由变量,这个时候使用最外层的作用域。
- 从实践角度:以下函数才算是闭包:
*即使创建它的上下文已经销毁,它仍然存在(比如,内部函数从父函数中返回)
*在代码中引用了自由变量
var funOne = (function(){
var num = 0;
return function(){
num++;
return num;
}
})();
console.log(funOne()); // 输出:1
console.log(funOne()); // 输出:2
console.log(funOne()); // 输出:3
三、作用域
1、定义
作用域是在运行时代码中的某些特定部分中变量,函数和对象的可访问性。换句话说,作用域决定了代码区块中变量和其他资源的可见性。
2、分类
(1)全局作用域
在代码中任何地方都能访问到的对象拥有全局作用域。
var outVariable = "我是最外层变量"; //最外层变量
function outFun() {
//最外层函数
var inVariable = "内层变量";
function innerFun() { //内层函数
console.log(inVariable);
}
innerFun();
}
console.log(outVariable); //我是最外层变量
outFun(); //内层变量
console.log(inVariable); //inVariable is not defined
innerFun(); //innerFun is not defined
(2)函数作用域
函数作用域,是指声明在函数内部的变量,和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到,最常见的例如函数内部。
function doSomething(){
var blogName="浪里行舟";
function innerSay(){
alert(blogName);
}
innerSay();
}
alert(blogName); // 报错
innerSay(); // 报错
(3)块级作用域
块级作用域可通过新增命令let和const声明,所声明的变量在指定块的作用域外无法被访问。
块级作用域有以下几个特点:
- 声明变量不会提升到代码块顶部
- 禁止重复声明
- 变量只在当前块内有效
for(var i = 0; i < 10; i++) {
setTimeout(function(){
console.log(i)
})
}
// 输出 10 10 10 10 10 10 10 10 10 10
for(let i = 0; i < 10; i++) {
setTimeout(function(){
console.log(i)
})
}
// 输出 0 1 2 3 4 5 6 7 8 9