我感兴趣的源码
1函数、对象的嵌套问题
题目1.1
会输出什么?
var func = new Function("console.log('我是func')");console.log(func());
题目1.2
会输出什么
var Cache1 = (function(){var cache = {};return {getObj1:function(name){if(name in cache){return cache[name];}var temp = new Object(name);cache[name] = temp;return temp;},getObj2:function(name){if(name in cache){return cache[name];}var temp = new Object(name);cache[name] = temp;return temp;}}})();console.log(Cache1);console.log(Cache1.getObj1('巧碧螺'));
2this相关的问题
2.1
var num = 20;var obj = {num:30,fn:(function (num) {this.num *= 3;num += 15;var num = 45;return function () {this.num *= 4;num += 20;console.log(this);console.log(num);}})(num)}var fn = obj.fn;fn();obj.fn();
2.2
function a(xx){this.x=xx;return this;}var x=a(5);console.log(x.x);var y=a(6);console.log(x.x);console.log(y.x);
2.3
请说明要输出正确的myName的值要如何修改程序?
Foo = function(){this.myName = "Foo function.";}Foo.prototype.sayHello = function(){alert(this.myName);}Foo.prototype.bar = function(){setTimeout(this.sayHello, 1000);}var f = new foo;f.bar();
2.4
var length = 10;function fn () {console.log(this.length);}var obj = {length: 5,method: function (fn) {fn();arguments[0]();},fn:function(){console.log(this);console.log(this.length);}};obj.method(obj.fn, 1);
2.5
window.val = 1;var obj = {val: 2,dbl: function () {this.val *= 2;val *= 2;console.log('val:', val);console.log('this.val:', this.val);}};// 说出下面的输出结果obj.dbl();var func = obj.dbl;func();
3闭包相关的问题
闭包相关题目套路
- 先判断是否构成闭包(两个条件)。
- 如果构成闭包,观察外部函数是否只执行了一次。
- 每一个外部函数对应一组缓存(一组对应变量的最终值)
- 往难了走,难点会变成找到外部函数、找到闭包。
- 根据外部函数执行次数,找到最终值,
- 注意区分var和let。
- 只需关注真正处于闭包中的变量。
3.1
var i = 0;function outerFn(){function innnerFn(){i++;console.log(i);}return innnerFn;}var inner1 = outerFn();var inner2 = outerFn();inner1();inner2();inner1();inner2();
3.2
function outerFn(){var i = 0;function innerFn(){i++;console.log(i);}return innerFn;}var inner = outerFn();inner();var inner2 = outerFn();inner2();inner2();inner();
3.3
function fn(){var arr = [];for(var i = 0; i < 5; i++){arr[i]= function(){return i;}}return arr;}var list = fn();for(var i = 0; i < list.length; i++){console.log(list[i]());}//----function fn(){var arr = [];for(let i = 0; i < 5; i++){arr[i]= function(){return i;}}return arr;}var list = fn();for(var i = 0; i < list.length; i++){console.log(list[i]());}
3.4
(function() {var m = 0;function getM() { return m; }function seta(val) { m = val; }window.g = getM;window.f = seta;})();f(100);console.log(g())
3.5
```javascript <!DOCTYPE html>
- 1
- 2
- 3
<a name="n1HKR"></a>### 3.6```javascriptvar fn = (function(){var i=10;function fn(){console.log(++i);}return fn;})()fn();fn();
答案
1
1.1
我是funcundefined
解析:
- console.log(函数的执行) ——>会先执行一次函数,再打印它的return对象
- 函数没有return或者没有返回值时会返回undefined
console.log(函数的名字,但不执行) ——>直接打印函数的代码
1.2

解析:输出1:
- Cache1本身是立即执行,所以console.log(函数的执行) ——>会先执行一次函数,再打印它的return对象
- 这次的return对象,是一个字面量表达的对象,分别有obj1和obj2两个方法。
- 输出2:
解析
- 自执行函数的this指向window
- 闭包涉及的局部变量会常驻内存
var num = 20; //window.numvar obj = { //obj.numnum:30,fn:(function (num) { //自执行函数新开的num,随便叫什么都可以this.num *= 3; //自执行函数的this指向windownum += 15;var num = 45; //会声明提前,但由于var可以反复声明,因此没有影响。//且因为不在最外层的window里,this.num和num是独立的、无关的return function () { //函数新开的num形成了闭包,会“常驻内存”this.num *= 4;num += 20;console.log(this);console.log(num);}})(num)//往上找,由于没有函数作用域,直接找到全局作用域。}var fn = obj.fn;//自执行函数只会执行一次,从此fn和obj.fn都是return值fn();obj.fn(); //!<==>fn();对于fn()而言,调用它的对象是window
答案:
window65obj85
2.2
解析:对于window,定义在最外层window上的var变量 和 window./this. 是一体的
function a(xx){this.x=xx;return this;}var x=a(5);//window.x = 5; window.x = window;console.log(x.x);//window.x = window,因此windowvar y=a(6);//window.x = 6; window.y = windowconsole.log(x.x);//第一个x是6,因此undefinedconsole.log(y.x);//window.y = window,而window.x = 6,因此6
答案:
windowundefined6
2.3
解析:普通函数的this根据调用者动态改变,而回调函数在执行时已经找不到调用者了(即使setTimeOut设置s),会指向window,因此需要改变的就是回调函数的this指向 / 把myName放在全局上。
- 方法
- 法一:箭头函数
因为箭头函数里面所有的this会与其第一层的this保持一致,在定义时静态决定,不会动态改变。
foo = function(){this.myName = "Foo function.";}foo.prototype.sayHello = function(){alert(this.myName);}foo.prototype.bar = function(){setTimeout(()=>{this.sayHello}, 1000);}var f = new foo;f.bar();
法二:使用bind,修改this指向。
- 注意这里不能用call和apply,否则setTimeOut会失去意义
- bind会储存this
foo = function(){this.myName = "Foo function.";}foo.prototype.sayHello = function(){alert(this.myName);}foo.prototype.bar = function(){setTimeout(this.sayHello.bind(this), 1000);}var f = new foo;f.bar();
法三:调用一次foo()
相当于把myName放到windows对象上
foo = function(){this.myName = "Foo function.";}foo.prototype.sayHello = function(){alert(this.myName);}foo.prototype.bar = function(){setTimeout(this.sayHello, 1000);}var f = new foo;foo();f.bar();
- 法四:添加参数that
foo = function(){this.myName = "Foo function.";}foo.prototype.sayHello = function(that){alert(that.myName);}foo.prototype.bar = function(){var that = this;setTimeout(function(){that.sayHello(that)}, 1000);}var f = new foo;foo();f.bar();
2.4
- 解析:
- 两次fn调用都调用的是obj.fn,但this指向都不是obj
- 对象方法中的方法指向window
- arguments 是一种特殊的对象,因此第二次fn的指向是arguments,而arguments.length = 2。 ```javascript var length = 10;
function fn () { console.log(this.length); }
var obj = { length: 5, method: function (fn) { fn(); arguments0; }, fn:function(){ console.log(this); console.log(this.length); } };
obj.method(obj.fn, 1);
- 答案:```javascriptwindow102
2.5
- 解析
- 因为js不存在块级作用域的概念,因此在非window作用域(即全局作用域)中调用不带this的变量时,会先从当前块中找,没有的话就从父块中找,直到找到window(window的挂载和var定义的变量是一体的)。
- 最后调用func()和obj.dbl是不一样的。 ```javascript window.val = 1;
var obj = {
val: 2,
dbl: function () {
this.val = 2;
val = 2;
console.log(‘val:’, val);
console.log(‘this.val:’, this.val);
}
};
// 说出下面的输出结果 obj.dbl(); var func = obj.dbl; func();
- 答案:```javascript2 4 8 8
3
3.1
- 解析
- 没有形成闭包
- 每次内部函数执行时的i,是炫从全局变量中获取的
- 没有形成闭包
答案
1 2 3 4
3.2
解析
- 构成闭包、外部函数执行两次、var
- 每重新执行一次外部函数,就会创建一组新的缓存。
function outerFn(){var i = 0;function innerFn(){i++;console.log(i);}return innerFn;}var inner = outerFn();inner();//1var inner2 = outerFn();inner2();//1inner2();//2inner();//2
- 每重新执行一次外部函数,就会创建一组新的缓存。
- 构成闭包、外部函数执行两次、var
答案
1 1 2 2
3.3
解析
- 构成闭包、外部函数只执行一次、需要区分var和let
- ①和②中外部函数都只执行了一次,则分别对应一组缓存,只不过①中只缓存了一个i值,②中缓存了5个i值
//①function fn(){var arr = [];for(var i = 0; i < 5; i++){arr[i]= function(){return i;//真正受缓存影响的只有这个i}}return arr;}var list = fn();for(var i = 0; i < list.length; i++){console.log(list[i]());}//②function fn(){var arr = [];for(let i = 0; i < 5; i++){arr[i]= function(){return i;//真正受缓存影响的只有这个i}}return arr;}var list = fn();for(var i = 0; i < list.length; i++){console.log(list[i]());}
- ①和②中外部函数都只执行了一次,则分别对应一组缓存,只不过①中只缓存了一个i值,②中缓存了5个i值
- 构成闭包、外部函数只执行一次、需要区分var和let
答案
5555501234
3.4
解析
- 每一次外部函数的执行会对应一组缓存。
答案
100
3.5
解析
- 构成闭包、外部函数执行了3次
- 该题目是事件处理函数总闭包的写法
答案
//需要点击3次: 0 1 2
3.6
解析
- 构成闭包、外部函数只执行了一次
test.html里那道题11 12
https://blog.csdn.net/Hunt_bo/article/details/107699137
- 构成闭包、外部函数只执行了一次
