作用域&变量提升&闭包&原型&继承__代码输出题
2022/4/6 23:24:53
本文主要是介绍作用域&变量提升&闭包&原型&继承__代码输出题,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1. 局部作用域中的意外全局变量
(function(){ var x = y = 1; })(); var z; console.log(y); console.log(z); console.log(x);
答案:1,undefined,报错 Uncaught ReferenceError: x is not defined
解析:
var x = y = 1;从右向左执行,y = 1,因为没有声明变量所以是全局window上的变量。而var x = 1;是自执行函数内的局部变量。所以最后输出x报错,因为没有定义。
2. 变量的作用域链
var a=3; function c(){ alert(a); } (function(){ var a=4; c(); })();
答案:3
解析:
js中变量的作用域链与定义时的环境有关,与执行时无关。执行环境只会改变this、传递的参数、全局变量等。
3. 变量提升/作用域
var a = 10; (function () { console.log(a); a = 5; console.log(window.a); console.log(a); var a = 20;// 如果var a=20改成let a = 20;打印什么 console.log(a); })()
答案:undefined、10、5、20;
如果改成 let a = 20;
答案:直接报错,let 声明 有暂时性死区(其实let声明提前了,但是不能用a,所以报错)。
4. 原型
// a function Foo () { getName = function () { console.log(1); } return this; } // b Foo.getName = function () { console.log(2); } // c Foo.prototype.getName = function () { console.log(3); } // d var getName = function () { console.log(4); } // e 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(), Foo为一个函数对象,对象都可以有属性,b 处定义Foo的getName属性为函数,输出2;
- getName(), 这里看d、e处,d为函数表达式,e为函数声明,两者区别在于变量提升,函数声明的 5 会被后边函数表达式的 4 覆盖;
- Foo().getName(), 这里要看a处,在Foo内部将全局的getName重新赋值为 console.log(1) 的函数,执行Foo()返回 this,这个this指向window,Foo().getName() 即为window.getName(),输出 1;
- getName(), 上面3中,全局的getName已经被重新赋值,所以这里依然输出 1;
- new Foo.getName(), 这里等价于 new (Foo.getName()),先执行 Foo.getName(),输出 2,然后new一个实例;
- new Foo().getName(), 这 里等价于 (new Foo()).getName(), 先new一个Foo的实例,再执行这个实例的getName方法,但是这个实例本身没有这个方法,所以去原型链__protot__上边找,实例.protot === Foo.prototype,所以输出 3;
- new new Foo().getName(), 这里等价于new (new Foo().getName()),如上述6,先输出 3,然后new 一个 new Foo().getName() 的实例。
5. 原型上的方法
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,报错Uncaught TypeError: f.b is not a function,a,b
解析:
- f 是 对象,不是Function的实例
- F 为构造函数,可以访问原型上的b( )方法
6. this的指向、原型、原型链、类的继承、数据类型
function Parent() { this.a = 1; this.b = [1, 2, this.a]; this.c = { demo: 5 }; this.show = function () { console.log(this.a , this.b , this.c.demo ); } } function Child() { this.a = 2; this.change = function () { this.b.push(this.a); this.a = this.b.length; this.c.demo = this.a++; } } Child.prototype = new Parent(); var parent = new Parent(); var child1 = new Child(); var child2 = new Child(); child1.a = 11; child2.a = 12; parent.show(); child1.show(); child2.show(); child1.change(); child2.change(); parent.show(); child1.show(); child2.show();
结果:
parent.show(); // 1 [1,2,1] 5 child1.show(); // 11 [1,2,1] 5 child2.show(); // 12 [1,2,1] 5 parent.show(); // 1 [1,2,1] 5 child1.show(); // 5 [1,2,1,11,12] 5 child2.show(); // 6 [1,2,1,11,12] 5解析:
parent.show()
,可以直接获得所需的值;child1.show()
,Child
的构造函数原本是指向Child
的,题目显式将Child
类的原型对象指向了Parent
类的一个实例,需要注意Child.prototype
指向的是Parent
的实例,而不是指向Parent
这个类。所以调用show
方法,this.a
自身有,其他属性从原型上获取。child2.show()
,同上;parent.show()
,parent
是一个Parent
类的实例,Child.prorotype
指向的是Parent
类的另一个实例,两者在堆内存中互不影响,所以上述操作不影响parent
变量,所以输出结果不变;child1.show()
,child1
执行了change()
方法后,发生了怎样的变化呢?
this.b.push(this.a)
,由于this的动态指向特性,this.b会指向Child.prototype
上的b数组,this.a会指向child1
的a属性,所以Child.prototype.b
变成了[1,2,1,11]
;this.a = this.b.length
,这条语句中this.a
和this.b
的指向与上一句一致,故结果为child1.a
变为4;this.c.demo = this.a++
,由于child1
自身属性并没有c这个属性,所以此处的this.c
会指向Child.prototype.c
,this.a
值为4,为原始类型,故赋值操作时会直接赋值,Child.prototype.c.demo
的结果为4,而this.a
随后自增为5(4 + + = 5)。child2
执行了change()
方法, 而child2
和child1
均是Child
类的实例,所以他们的原型链指向同一个原型对象Child.prototype
,也就是同一个parent
实例,所以child2.change()
中所有影响到原型对象的语句都会影响child1
的最终输出结果。
- this.b.push(this.a),由于this的动态指向特性,this.b会指向
Child.prototype
上的b数组,this.a会指向child2
的a属性,所以Child.prototype.b
变成了[1,2,1,11,12]
;- this.a = this.b.length,这条语句中
this.a
和this.b
的指向与上一句一致,故结果为child2.a
变为5;- this.c.demo = this.a++,由于
child2
自身属性并没有这个属性,所以此处的this.c
会指向Child.prototype.c
,故执行结果为Child.prototype.c.demo
的值变为child2.a
的值5,而child2.a
最终自增为6(5 + 1 = 6)。
这篇关于作用域&变量提升&闭包&原型&继承__代码输出题的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2025-01-04敏捷管理与看板工具:提升研发、设计、电商团队工作效率的利器
- 2025-01-04智慧养老管理工具如何重塑养老生态?
- 2025-01-04如何打造高绩效销售团队:工具与管理方法的结合
- 2025-01-04解决电商团队协作难题,在线文档工具助力高效沟通
- 2025-01-04春节超市管理工具:解锁高效运营与顾客满意度的双重密码
- 2025-01-046种主流销售预测模型:如何根据场景选用最佳方案
- 2025-01-04外贸服务透明化:增强客户信任与合作的最佳实践
- 2025-01-04重新定义电商团队协作:在线文档工具的战略作用
- 2025-01-04Easysearch Java SDK 2.0.x 使用指南(三)
- 2025-01-04百万架构师第八课:设计模式:设计模式容易混淆的几个对比|JavaGuide