变量的生成查找
var bar=1;
var bar=1;
var bar 编译器先会查询作用域是否存在变量bar?
作用域
- 存在: 忽略这个变量声明,往下执行
- 不存在: 就在当前作用域生成一个新的变量命名为bar
然后生成bar=1能够被引擎执行的代码
runtime
引擎执行时,会在作用域中查找是存在bar
- 存在: 赋值为1
- 不存在: 去上一层作用域查找
foo, bar, baz其实这些词没有任何意思, 通常当作占位符使用
-
foo: first object oriented 第一个面向对象
-
bar: binary arbitrary reason 任意二进制原因
Scope(作用域)
作用域就是根据变量名称查询变量的规则。
function foo(){
var bar = 1;
function baz(){
console.log(bar);
}
baz();
}
运行foo(), 打印输出 bar
- 在 baz 函数中查找变量 bar
- 不存在, 去上一层作用域foo查找
- 存在, 获取 foo 中 bar 的值
上下文
this 的指向, 是根据当前的执行上下文动态决定的
- 在简单调用时, this 默认指向的是 window / global / undefined ( 浏览器 / node / 严格模式 )
- 在对象调用时,指向的是当前对象
- 在使用 call / apply / bind 时,指向的是绑定的对象
- 使用 new 关键字, 指向新创建的对象
优先级: new > call/apply/bind > 对象调用 - 箭头函数根据外层的规则确定。
var number = 10;
var obj = {
number: 5,
fn1: (function () {
var number;
this.number *= 2;
number = number * 2;
number = 3;
return function () {
var num = this.number;
this.number *= 2;
console.log(num);
number *= 3;
console.log(number);
}
})()
}
var fn1 = obj.fn1;
fn1.call(null);
obj.fn1();
console.log(window.number);
var fn1 = obj.fn1;由于obj.fn1是IIFE(立即执行函数), 返回一个函数, 形成一个闭包,因为是简单调用,this指向window,this.number *= 2;最外层number变成 20;number = number * 2; number = 3;闭包中变量number赋值为 3;fn1.call(null);使用call绑定值为null,fn1中this指向是window,this.number *= 2;最外层number变成 40;console.log(num);打印输出 20;number *= 3;在词法作用域中查找到闭包变量number并进行计算变成9;console.log(number);打印输出9;obj.fn1();执行,fn1中this指向是obj,console.log(num);打印输出5,number *= 3;闭包变量number并进行计算变成9*3=27, 打印输出27- 此时
window中number为40,打印输出40
call 简单实现
Function.prototype.callN = function(context,...rest){
context.fn = this;
if(context){
const result = context.fn(...rest);
delete context.fn;
return result;
}else{
this(...args)
}
}
bind 简单实现
Function.prototype.bindN=function(context,...rest){
const fn=this;
return function(...innerRest){
const args=[...rest,...innerRest];
fn.call(context,...args);
// context.fn = fn;
// if(context){
// const result= context.fn(...args);
// delete context.fn;
// return result
// }else{
// this(...args)
// }
}
}