原稿:语雀 · JS 基础题目 · 原目录:面向面经学习 › JS 基础题目

作用域

var temp = 1;
function test() {
  temp = 10;
  return;
  function temp() {}
}
test();
console.log(temp);
image.png

结果为1,因为在 test() 中的函数声明会被提升,相当于在函数作用域中有一个局部变量 temp,之后执行 temp=10 是重新赋值这个局部变量,没有修改全局作用域的 temp;

拓展:当注释掉 function temp() {} ,会输出 10,因为在函数内定义变量时省略 var 时会在全局上下文中创建一个全局变量


作用域

function Foo() {
    getName = function () {
        console.log(1);
    };
    return this;
};
Foo.getName = function () {
    console.log(2);
};
Foo.prototype.getName = function () {
    console.log(3);
};
var getName = function () {
    console.log(4);
};
function getName() {
    console.log(5);
};

Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();

// 结果
//
//
//
//2 4 1 1 2 3 3
  • 第三句:典型的作用域污染,Foo()执行中,getName 未使用 var 声明,因此优先沿作用域链寻找,并在全局作用域中找到,这里污染了全局作用域中的 getName

注意执行优先级“成员访问优先级 = new 有参构造 > new 无参构造”,new Foo 等同于 new Foo(),前者是无参构造,后者是有参构造:

  • new Foo.getName():相当于 new(Foo.getName())
  • new Foo().getName():相当于 (new Foo()).getName()
  • new new Foo().getName():相当于 new ((new Foo()).getName())

var F = function() {};
Object.prototype.a = function() {
  console.log('a');
};
Function.prototype.b = function() {
  console.log('b');
};
var f = new F();
f.a();
f.b();
F.a();
F.b();

//结果: a TypeError: f.b is not a function a b
  1. 在对象 f 上寻找属性 a 未果;沿原型链进入 F.prototype,后者是一个 Object 实例,寻找属性 a 依旧未果;沿原型链进入 Object.prototye,找到并调用
  2. 在对象 f 上寻找属性 b 未果;在整个原型链上都无法找到属性 b,抛出错误
  3. 在对象 F 上寻找属性 a 未果;沿原型链进入 Function.prototype,后者是一个 Object 实例,寻找属性 a 依旧未果;沿原型链进入 Object.prototye,找到并调用
  4. 在对象 F 上寻找属性 b 未果;沿原型链进入 Function.prototype,找到并调用 b

原型链

function Person(name) {this.name = name;}Person.prototype.print = function() {return this.name;};Person('abc');const a = new Person('abc').print.call({});console.log(a);const fn = () => {this.x = 'z';};const b = {x: 'y'};fn.call(b);console.log(b);// undefined// {x: 'y'}
  • new Person(‘abc’).print.call({}):实际上等于 person.print.call({}),显式绑定>隐式绑定
  • fn.call(b):箭头函数没有 this,不存在修改绑定的说法,也不能修改箭头函数定义位置作用域的 this

原型链

var a= function () { this.b =3; }var c = new a();a.protorype.b = 9;var b = 7;a();console.log(b);console.log(c.b);// 3 3

相信自己哈,c 上确实在对象和原型上都存在 b 属性


原型链

Function.prototype.a = () => alert(1);
Object.prototype.b = () => alert(2);
function A() {};
var a = new A();
a.a();
a.b();

// 报错 Uncaught TypeError: a.a is not a function

作用域

var x = 10;

function fn(){
    console.log(x);
}

function show(f){
    var x = 20;
    (function(){
       f();
    })()
}

show(fn);

// 打印10,因为fn执行时,外层作用域直接是window