(前端推荐)作用域链与原型链

112 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情

1 作用域链

1 作用域是什么

作用域 就是变量的有效范围。

  • 1、全局作用域: 最外层函数定义的变量拥有全局作用域,即对任何内部函数来说,都是 可以访问的;
  • 2、局部作用域: 局部作用域一般只在固定的代码片段内可访问到,而对于函数外部是无 法访问的,最常见的例如函数内部。
  • 3、块级作用域:凡是代码块就可以划分变量的作用域,这种作用域的规则就叫块级作用域。

image.png

2 块级作用域 函数作用域 词法作用域之间的区别

块级作用域和函数作用域描述的是,什么东西可以划分变量的作用域 词法作用域描述的是,变量的查找规则 之间的关系:

  • 1、 块级作用域 包含 函数作用域
  • 2、词法作用域 与 块级作用域、函数作用域之间没有任何交集

3 作用域链

作用域链本质是最底层的变量查找机制,即就近原则会有限查找当前函数作用域的变量 查找不到则会依次逐级查找父级作用域

function fn() {
 //外部函数 
let num = 20; 
function fun() { //内部函数 
console.log (num); //输出结果: 20 
} 
fun() ; 
} 
fn() ; 


image.png

2 原型链

1 原型

在JavaScript中是使用构造函数来新建一个对象的,每一个构造函数的内部都有一个 prototype 属性,它的属性值是一个对象,这个对象包含了可以由该构造函数的所有实例共享的属性和方法。

image.png

当使用构造函数新建一个对象后,在这个对象的内部将包含一个指针,这个指针指向构造函数的 prototype 属性对应的值,在 ES5 中这个指针被称为对象的原型。一般来说不应该能够获取到这个值的,但是现在浏览器中都实现了 proto 属性来访问这个属性,但是最好不要使用这个属性,因为它不是规范中规定的。ES5 中新增了一个 Object.getPrototypeOf() 方法,可以通过这个方法来获取对象的原型。

2 原型链

当访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型对象里找这个属性,这个原型对象又会有自己的原型,于是就这样一直找下去,也就是原型链的概念。

原型链的尽头一般来说都是 Object.prototype 所以这就是新建的对象为什么能够使用 toString() 等方法的原因。

image.png

function Person(username) {
    this.username = username
}
// 修改原型
Person.prototype.getUsername = function() {}
var p = new Person('今天也要快乐的搬砖呀!')
console.log(p.__proto__ === Person.prototype) // true
console.log(p.__proto__ === p.constructor.prototype) // true
// 重写原型
Person.prototype = {
    getUsername: function() {}
}
var p = new Person('今天也要快乐的搬砖呀!')
console.log(p.__proto__ === Person.prototype)        // true
console.log(p.__proto__ === p.constructor.prototype) // false

可以看到修改原型的时候p的构造函数不是指向Person了,因为直接给Person的原型对象直接用对象赋值时,它的构造函数指向的了根构造函数Object,所以这时候p.constructor === Object ,而不是p.constructor === Person。要想成立,就要用constructor指回来:

Person.prototype = {
    getUsername: function() {}
}
var p = new Person('今天也要快乐的搬砖呀!')
p.constructor = Person
console.log(p.__proto__ === Person.prototype)        // true
console.log(p.__proto__ === p.constructor.prototype) // true

打印原型链的终点 由于Object是构造函数,原型链终点是Object.prototype.__proto__,而Object.prototype.__proto__=== null // true,所以,原型链的终点是null。原型链上的所有原型都是对象,所有的对象最终都是由Object构造的,而Object.prototype的下一级是Object.prototype.__proto__

image.png


如何获得对象非原型链上的属性?

function iterate(obj){
   var res=[];
   for(var key in obj){
        if(obj.hasOwnProperty(key))
           res.push(key+': '+obj[key]);
   }
   return res;
} 

好啦,今天就这样吧!!!

image.png