1、作用域链 -- 要到创建这个函数的那个作用域中取值——是“创建”,而不是“调用”
如果代码中只有声明没有赋值,显示 undefined
如果既无声明也没赋值,就会报错
var a=10; function f1(){ var b=20; function f2(){ // 当前作用域没有此变量时,逐级往父作用域上面找 var c = 30; console.log(a) // 自由变量 console.log(b) // 自由变量 console.log(c) } f2() } f1()
2、闭包
闭包的使用场景
1、函数作为返回值
2、函数作为参数传递-----要到创建这个函数的那个作用域中取值——是“创建”,而不是“调用
function F1() { var a = 10; //如果这条代码消失,a会取上一级作用域的值 console.log('b') return function () { console.log(a) // a 为自由变量 } } var f1 = F1(); var a = 20; // f1(); // 10 function F2(fn){ var a=30; // a不会取调用它的作用域的值 fn() } F2(f1) // 10
3、原型链
在访问对象的属性和方法时, 会在当前对象中查找, 如果没有找到, 会一直沿着原型链上的原型对象__proto__向上查找, 直到找到Object.prototype(原型的顶端)
为止,这就是原型链。
function Dog() { this.eat = function () { console.log('喜欢吃骨头') } } function Cat() { this.food = function () { console.log('喜欢吃鱼') } } Cat.prototype.weight=function(){ console.log('不重') } Dog.prototype = new Cat(); var dog = new Dog(); dog.eat() // 喜欢吃骨头 dog.food() // 喜欢吃鱼 dog.weight() // Cat的原型对象的方法会被继承下来