目录
相关链接
- 相关链接
- 1、题_1
- 2、使用for循环打印0-9
- 3、10的N次方
- 4、N的阶乘
- 5、打印三个数中的最大值
- 6、打印100以内的质数
- 7、undefined、null、0的比较
- 8、if圆括号里的函数表达式以及关于if的真假条件
- 9、函数执行与单独的一句话
- 10、变量式自执行函数生成闭包
- 11、实参与形参的映射关系
- 12、变量提升之函数调用及覆盖
- 13、同步任务、宏任务、微任务、setTimeout、Promise、then
- 14、原型对象和实例对象、Object、create
- 15、new、prototype
- 16、array、reverse、push、slice、length
- 17、链式调用、this、箭头函数
- 18、根据字符串固定值重组数组
- 19、包装类型
- 20、构造函数之this
- 21、函数名不同,执行方式不同
- 22、函数的形参和实参映射关系
1.1、大千世界-26 道 JS 烧脑面试题大赏
1、题_1let result = [], a = 3, total = 0; function foo(a) { for (let i = 0; i < 3; i++) { result[i] = function () { total += i * a; console.log(total); } } } foo(1); result[0](); // 3 result[1](); // 6 result[2](); // 92、使用for循环打印0-9
使用for循环打印0-9,()中只能写一句话,且不能写比较;{}里面不能出现++或--
let i = 10; for(; i--;) console.log(i);3、10的N次方
let sum = 1; for(let i = 0; i < 5; i++) sum *= 10; console.log(sum); // 1000004、N的阶乘
let num = 1; for(let i = 1; i <= 5; i++) num *= i; console.log(num); // 1205、打印三个数中的最大值
let a = 1, b = 2, c = 3; console.log(a > b && a > c ? a : b > c ? b : c); // 36、打印100以内的质数
质数:仅仅能被1和自身整除的数,1不是质数。
let c = 0; for (let i = 0; i < 100; i++) { for (let j = 1; j <= i; j++) if (i % j == 0) c++; if (c == 2) console.log(i); c = 0; }7、undefined、null、0的比较
console.log(undefined > 0); // false console.log(undefined < 0); // false console.log(undefined == 0); // false console.log(null > 0); // false console.log(null < 0); // false console.log(null == 0); // false console.log(undefined > null); // false console.log(undefined < null); // false console.log(undefined == null); // true console.log(undefined === null); // false8、if圆括号里的函数表达式以及关于if的真假条件
false、0、undefined、null、空字符串、NaN在if表达式中返回结果都是假。
var a = 7, fn = function () { // if (function b() { }) => (function b() { }) // 只是没有执行而已 // (function b() { console.log(7); })() // 此写法最终结果会省略掉函数名,也就是b // if只有遇到 // false、0、undefined、null、空字符串、NaN的时候才为假 // 其余都为真 // if (!false && !0 && !undefined && !null && !'' && !NaN) console.log(7); // 7 if (function b() { }) a += typeof (b); console.log(a); // 7undefined }; fn();9、函数执行与单独的一句话
function a(params) { console.log(arguments); return params; } a(3, 5, 7); // 打印 Arguments(3) [3, 5, 7, callee: ƒ, Symbol(Symbol.iterator): ƒ] (function a(params) { console.log(arguments); return params; })(1, 5, 9); // 打印 Arguments(3) [1, 5, 9, callee: ƒ, Symbol(Symbol.iterator): ƒ] function a(params) { console.log(arguments); return params; } (1, 2, 3); // 此处没有打印 // 因为函数不执行 // (1, 2, 3); 相当于单独的一句话, // 跟函数没有任何联系10、变量式自执行函数生成闭包
let closure = (function () { let a = 0; function closure() { a++; console.log(a); } // 自执行函数里面的函数名只是迷惑而已 // 它与全局定义的变量互不影响 return closure; })(); closure(); // 1 closure(); // 2 closure(); // 311、实参与形参的映射关系
函数的实参与形参之间相互映射,相互影响。前提是一一对应,如果形参和实参个数不同,无法达到一一映射关系。
function formalParameterAndArgumentMapping(x, y, z) { x = 10; console.log(arguments[0]); // 10 arguments[1] = 20; console.log(y); // 20 z.z = 30; console.log(z.z); // 30 arguments[2].z = 40; console.log(z.z); // 40 } formalParameterAndArgumentMapping(1, 2, { z: 3 });12、变量提升之函数调用及覆盖
函数在提升时,函数名一样,最终会保留最后提升的函数及函数体。
let x = 1, y = z = 0; function add(n) { return n = n = 1; } y = add(x); function add(params) { return params = params + 2; } z = add(x); console.log(x, y, z); // 1 3 313、同步任务、宏任务、微任务、setTimeout、Promise、then
setTimeout(function () { console.log(1); }, 0); new Promise(function (resolve) { console.log(2); for (var i = 0; i < 1000; i++) { i == 9999 && resolve(); } console.log(3); }).then(function () { console.log(4); }); // 2 3 5 4 114、原型对象和实例对象、Object、create
const person = { address: { country: "china", city: "hangzhou" }, say: function () { return `it's ${this.name}, from ${this.address.country}`; }, setCountry: function (country) { this.address.country = country; } }; const p1 = Object.create(person); const p2 = Object.create(person); p1.name = "Matthew"; p1.setCountry("American"); p2.name = "Bob"; p2.setCountry("England"); console.log(p1.say()); // it's Matthew, from England console.log(p2.say()); // it's Bob, from England
因为name通过实例创建 所以name是实例上的属性 而address、say和setCountry通过对象直接创建 所以会挂载到对象的prototype对象上 p1和p2调用setCountry改变的都是prototype的内容 不管有多少个实例 只要是同一个对象 那么它们就共用prototype对象
15、new、prototypefunction 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(); // 2 // 全局有一个一模一样的表达式 // 所以调用的就是那个函数 getName(); // 4 // 在此处调用时 // 全局同名变量已经发生了赋值 // 赋值为console.log(4) Foo().getName(); // 1 // 这里调用了函数的静态方法 // 所以全局的函数又一次发生了赋值 // ‘又一次’是针对预编译过程 getName(); // 1 // 因为调用了Foo().getName() // 调用Foo().getName()时 // 全局getName发生了重新复制 // 所以这里的值变为了1 new Foo.getName(); // 2 // new操作符用来执行函数 // 所以new Foo.getName()相当于new (Foo.getName)() // 所以new的是Foo的静态方法getName new Foo().getName(); // 3 // 因为点运算符(.)的优先级和new一样高 // 所以从左往右执行 // 相当于(new Foo()).getName() // 对Foo使用new调用会返回一个新创建的对象实例 // 然后执行该对象的getName方法 // 该对象本身并没有该方法 // 所以会从Foo的原型对象上查找 new new Foo().getName(); // 3 // 因为点运算符(.)的优先级和new一样高 // new操作符用来执行函数 // 所以new new Foo().getName()相当于new ((new Foo()).getName)()16、array、reverse、push、slice、length
var arr1 = 'john'.split(''), arr2 = arr1.reverse(), arr3 = 'jones'.split(''); arr2.push(arr3); console.log(arr1); // ['n', 'h', 'o', 'j', Array(5)] console.log(arr2); // ['n', 'h', 'o', 'j', Array(5)] console.log('array1: length = ' + arr1.length + ' last = ' + arr1.slice(-1)); // array1: length = 5 last = j,o,n,e,s console.log('array2: length = ' + arr2.length + ' last = ' + arr2.slice(-1)); // array2: length = 5 last = j,o,n,e,s
split分割字符串,并且存到数组中,如果split没有参数,那么就按字符分割;reverse翻转数组;slice截取数组中的值,只有一个参数,且值为-1时,截取数组最后一项。
17、链式调用、this、箭头函数var sched = { a: function() { console.log('a'); return this; }, b: function() { console.log('b'); return this; }, c: () => { console.log('c'); return this; }, d: () => { console.log('d'); return this; }, }; sched.a().b().c().d(); // 调用d的时候报错 // 因为在箭头函数中this的固定指向 // Uncaught TypeError: sched.a(...).b(...).c(...).d is not a function18、根据字符串固定值重组数组
function recombination(params) { let newArray = [], i = 0; for (; i < params.length; i++) if (/(a7)/.test(params[i])) newArray.push(params[i]); return newArray; } console.log(recombination(['7a7', '66agg', '3jk', '6a79', 'aa6', '886'])); // ['7a7', '6a79']19、包装类型
let names = 'languiji'; names += 10; let type = typeof (names); // 'string' // 如果先加包装,结果节能输出'string' // let type = new String(typeof (names)); if (type.length === 6) type.text = 'string'; // new String(type).text = 'string'; // 但是没有变量接收,所以type里面就没有了text这个属性 console.log(type.text); // undefined20、构造函数之this
function Test(a, b, c) { let d = 1; this.a = a; this.b = b; this.c = c; function f() { d++; console.log(d); } this.g = f; // 隐式返回this -> 形成闭包 } let test1 = new Test(); test1.g(); // 2 test1.g(); // 3 let test2 = new Test(); test2.g(); // 221、函数名不同,执行方式不同
function foo1(x) { console.log(arguments); // Arguments(5) [1, 2, 3, 4, 5, callee: ƒ, Symbol(Symbol.iterator): ƒ] return x; } foo1(1, 2, 3, 4, 5); function foo2(x) { console.log(arguments); return x; } (1, 2, 3, 4, 5); // 后面的圆括号相当于语句,不参与执行,也不是函数调用 // 所以不会执行 (function foo3(x) { console.log(arguments); // Arguments(5) [1, 2, 3, 4, 5, callee: ƒ, Symbol(Symbol.iterator): ƒ] return x; })(1, 2, 3, 4, 5);22、函数的形参和实参映射关系
function b(x, y, a) { a = 10; console.log(arguments[2]); // 10 } b(1, 2, 3);