题目一 箭头函数
var a = 10
var obj = {
a: 20,
say: () => {
console.log(this.a)
}
}
obj.say()
var anotherObj = { a : 30 }
obj.say.apply(anotherObj)
10、10
- 箭头函数是没有this的,是指向定义时外层的this
- 因为没有this,所以即使使用apply也没什么作用
这道题一般会再问一句,如果say变成普通函数会是什么样的结果,那就完全不同了。依稀记得几年前的面试好像就遇到过。😄
变为普通函数后就是:20、30
题目二
function a() {
console.log(this)
}
a.call(null)
解析:call如果传入的参数是null或者undefined,则把window作为this的值。例如也可以看我们手写的call,也是会做个判断。
Function.prototype.call2 = function(context) {
if (typeof this !== 'function') {
throw new Error('type error');
}
context = context || window; // context false则取windows
const args = [...arguments].slice(1);
context.fn = this;
const res = context.fn(...args);
delete context.fn;
return res;
}
题目三
var obj = {
name: 'cuggz',
fun: function() {
console.log(this.name)
}
}
obj.fun()
new obj.fun()
解析:想想new的操作,会构造一个新对象,然后函数将this改变为内部新创建的对象,但现在并没有什么name属性,所以是undefined
cuggz、undefined
function myNew() {
// 取出第一个参数,就是构造函数
const constructor = Array.prototype.shift.call(arguments);
if (typeof constructor !== 'function') {
throw new Error('not function');
}
const o = new Object;
// 原型指向构造函数原型
o.__proto__ = constructor.prototype;
// 改变构造函数的this,使它指向新创建的对象,o可以访问到构造函数的属性。apply参数是数组,call是一个一个的
const res = constructor.apply(o, arguments);
return typeof res === 'object' ? res : o;
}
题目四
var obj = {
say: function() {
var f1 = () => {
console.log("1111", this);
}
f1();
},
pro: {
getPro: () => {
console.log(this);
}
}
}
var o = obj.say;
o();
obj.say();
obj.pro.getPro();
解析:这个题目易错的是最后一行,还是考察的箭头函数的this,箭头函数是没有this的,取的是外层作用域的this,而对象是无法构成作用域的,所以this只能是最外层的,而最外层就是windows,再用babel编译看看最后结果就知道了
windows obj windows
题目五
var obj = {
number: 3,
db1: (function() {
console.log(this);
this.number *= 4;
return function() {
console.log(this);
this.number *= 5;
}
})()
}
var db1 = obj.db1
db1();
obj.db1();
console.log(obj.number);
console.log(window.number);
解析:
- db1是立即执行函数,立即执行this是windows,这时候执行this.number *= 5; 实际上没有number,所以是NAN。
- obj.db1实际上是里面返回的函数
- 其次就是this指向, obj.db1的this是obj
题目六
var length = 10
function fn() {
console.log(this.length)
}
var obj = {
length: 5,
method: function(fn) {
fn();
arguments[0]()
}
}
obj.method(fn, 1);
解析:这个题有坑,arguments0 竟然是2!!!相当于argumens.fn()。。。
10、2
题目七
var a = 10;
var obt = {
a: 20,
fn: function() {
var a = 30;
console.log(this.a)
}
}
obt.fn();
obt.fn.call();
(obt.fn)()
解析:最后一个加括号和不加效果一样,所以是20
20、10、20
题目8
function a(xx) {
console.log(this);
this.x = xx;
return this;
}
var x = a(5);
var y = a(6);
console.log(x.x);
console.log(y.x);
解析:undefined 6
这个题很具有迷惑性啊,不理解的地方估计就是x.x, 这里原因是y = a(6)后,window.x被更新为6,而x.x = window.x.x, 所以是undefined
题目9
function foo(something) {
this.a = something
}
var obj1 = {}
var bar = foo.bind(obj1)
bar(2)
console.log(obj1.a)
var baz = new bar(3);
console.log(obj1.a)
console.log(baz.a);
2 2 3
解析:这里可能疑惑的就是最后new bar,考察的知识点就是bind函数,如果是用new调用,则忽略传入的obj,还是原来初始函数的this
/**
* 返回一个新的函数
* 函数参数接收bind的函数和调用的函数,bind函数拼接调用函数构成最后参数
* 如果bind后的函数通过new来调用,则忽略bind绑定的context,使用原来构造函数上下文
*/
Function.prototype.bind2 = function(context) {
const outArgs = [...arguments].slice(1);
const func = this;
function fBound() {
const inArgs = [...arguments];
// 这里判断如果调用时this还是指向了F,则说明是new调用,上下文还是传入当前this
return func.apply(this instanceof F ? this : context, outArgs.concat(inArgs));
}
function F() {}
F.prototype = this.prototype;
fBound.prototype = new F();
return fBound;
}
题目10
var foo = 1;
function fn() {
foo = 3;
return;
function foo() {
// todo
}
}
fn();
console.log(foo);
里面foo的更新只会影响到内部foo的定义,不会影响到外面。
1 以上题目来自前端面试题之代码输出篇,记录做的时候可能有疑惑的题。