【前端面试之JS】什么是作用域链、原型链

1、作用域

作用域就是变量、函数生效的区域
一般将作用域分为:
全局作用域
函数作用域
块级作用域

1、全局作用域
任何不在函数或者花括号里面声明的变量,都是全局变量

var a = 1;
let b = 2;
const c = 3;
console.log(a);
console.log(b);
console.log(c);
{
    console.log(a);
    console.log(b);
    console.log(c);
}
(function haha() {
    console.log(a);
    console.log(b);
    console.log(c);
})()
输出:1,23,12,31,23

2、函数作用域
如果说一个变量在函数内部声明,那么就不能在函数外部去访问他。

(function haha() {
    var a = 1;
    let b = 2;
    const c = 3;

})()
console.log(a);
console.log(b);
console.log(c);

输出:Uncaught ReferenceError: a is not defined

3、块级作用域
在花括号中使用letconst声明的变量存在于块级作用域中。外部无法访问到。由{}包裹起来。var声明的变量是个例外。

 {
    var a = 1;
    let b = 2;
    const c = 3;
}
console.log(a);
console.log(b);
console.log(c);

输出1   Uncaught ReferenceError: b is not defined

2、语法作用域

变量被创建时就确定好了,而非执行阶段确定的。也就是说我们写好代码时它的作用域就确定了。
变量会被初始化为undefined(var声明的情况下)和保持uninitialized(未初始化状态)(使用let和const声明的情况下)

正是因为有了语法作用域,因此才会导致下面的错误

var a = 1;
function hah() {
     console.log(a)
 }
 hah()
 输出:1

但是如果改为如下语句,就会报错。

var a = 1;
function hah() {
   console.log(a)
   let a;
}
hah()
输出:Cannot access 'a' before initialization
原因:就是因为存在语法作用域,使得,在变量创建的时候,重新指定了a的作用域,又因为属于语句在创建语句之前,因此才会报错。

3、原型

每个对象都有一个原型对象
当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾

function hah() { }
console.log(hah.prototype)

在这里插入图片描述
其中的constructor,这个属性指向该函数。
在这里插入图片描述

4、原型链

原型对象也会拥有原型,从中继承方法以及属性。这就是原型链。
对象实例以及他的构造器之间也建立了一个连接(__proto__)属性,是从构造函数的prototype属性中派生出来的。

function Person(name) {
    this.name = name;
}
let zhangsan = new Person('张三');
console.log(zhangsan.__proto__)
console.log(zhangsan.__proto__ === Person.prototype)

在这里插入图片描述

function Person(name) {
    this.name = name;
}
let zhangsan = new Person('张三');
console.log(zhangsan.__proto__)
console.log(zhangsan.__proto__ === Person.prototype)//true
console.log(Person.prototype.__proto__ === Object.prototype)//true
console.log(Object.prototype.__proto__ === null)//true
  • 一切对象都是继承自Object对象,Object对象直接继承根源对象null

注意:数组的遍历方法for...in...,会遍历整个原型链。

function Person(name) {
    this.name = name;
}
let zhangsan = new Person('张三');
Object.prototype.age = 12
for (item in zhangsan) {
    console.log(item)
}
输出:name、age
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值