1 Menggunakan jenis bar === "objek" untuk menentukan sama ada bar ialah objek mempunyai potensi kelemahan? Bagaimana untuk mengelakkan kelemahan ini?
Kelemahan menggunakan typeof adalah jelas (kelemahan ini adalah sama seperti menggunakan instanceof):
let obj = {}; let arr = []; console.log(typeof obj === 'object'); //true console.log(typeof arr === 'object'); //true console.log(typeof null === 'object'); //true
Daripada keputusan output di atas, dapat dilihat bahawa jenis bar = == "objek" tidak Ia tidak boleh ditentukan dengan tepat bahawa bar ialah Objek. Anda boleh mengelakkan kelemahan ini dengan Object.prototype.toString.call(bar) === "[objek Objek]":
let obj = {}; let arr = []; console.log(Object.prototype.toString.call(obj)); //[object Object] console.log(Object.prototype.toString.call(arr)); //[object Array] console.log(Object.prototype.toString.call(null)); //[object Null]
Selain itu, untuk menghargai kehidupan, sila jauhi == :
Dan [] === false returns false.
Artikel berkaitan yang disyorkan: Koleksi soalan temuduga js paling lengkap pada tahun 2020 (terkini)
2 Adakah kod berikut akan mengeluarkan mesej pada konsol? kenapa?
(function(){ var a = b = 3; })(); console.log("a defined? " + (typeof a !== 'undefined')); console.log("b defined? " + (typeof b !== 'undefined'));
Ini berkaitan dengan skop pembolehubah Output ditukar kepada yang berikut:
console.log(b); //3 console,log(typeof a); //undefined
Nyahpasang penugasan pembolehubah dalam fungsi laksana sendiri:
b = 3; var a = b;
Jadi b menjadi pembolehubah global dan a ialah pembolehubah setempat bagi fungsi laksana sendiri.
3. Adakah kod berikut akan mengeluarkan mesej pada konsol? kenapa?
var myObject = { foo: "bar", func: function() { var self = this; console.log("outer func: this.foo = " + this.foo); console.log("outer func: self.foo = " + self.foo); (function() { console.log("inner func: this.foo = " + this.foo); console.log("inner func: self.foo = " + self.foo); }());
Tidak sukar untuk menilai output pertama dan kedua Sebelum ES6, JavaScript hanya mempunyai skop fungsi, jadi IIFE dalam func mempunyai skop bebasnya sendiri, dan ia boleh diakses sendiri. dalam skop luaran, jadi output ketiga akan melaporkan ralat kerana ini tidak ditentukan dalam skop boleh diakses, dan output keempat ialah bar. Jika anda tahu penutupan, mudah untuk diselesaikan:
function(test) { console.log("inner func: this.foo = " + test.foo); //'bar' console.log("inner func: self.foo = " + self.foo); }(self));
Jika anda tidak biasa dengan penutupan, anda boleh merujuk artikel ini: Bercakap tentang penutupan daripada rantai skop
4. Tukar kod JavaScript Apakah maksud memasukkannya ke dalam blok fungsi? Mengapa melakukan ini?
Dalam erti kata lain, mengapa menggunakan Ungkapan Fungsi yang Diseru Serta-merta?
IIFE mempunyai dua senario penggunaan klasik, satu serupa dengan kerap mengeluarkan item data dalam gelung, dan satu lagi serupa dengan pemalam JQuery/Node dan pembangunan modul.
for(var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }, 1000); }
Output di atas bukanlah 0, 1, 2, 3, 4 seperti yang anda fikirkan, tetapi semua output ialah 5, maka IIFE boleh berguna:
for(var i = 0; i < 5; i++) { (function(i) { setTimeout(function() { console.log(i); }, 1000); })(i) }
Dalam pembangunan pemalam dan modul JQuery/Node, untuk mengelakkan pencemaran berubah-ubah, ia juga merupakan IIFE yang besar:
(function($) { //代码 } )(jQuery);
5. ) Apakah faedah pembangunan?
Hapuskan beberapa aspek sintaks Javascript yang tidak munasabah dan tidak tepat, dan kurangkan beberapa gelagat pelik;
Hapuskan beberapa aspek yang tidak selamat dalam kod berjalan dan pastikan keselamatan kod berjalan;
Tingkatkan kecekapan pengkompil dan tingkatkan kelajuan larian;
membuka laluan untuk versi baharu Javascript pada masa hadapan.
6. Adakah nilai pulangan kedua-dua fungsi berikut adalah sama? kenapa?
Pertama ialah menaikkan kuasa dahulu dan kemudian menurunkan kuasa:
function add(num1, num2){ let r1, r2, m; r1 = (''+num1).split('.')[1].length; r2 = (''+num2).split('.')[1].length; m = Math.pow(10,Math.max(r1,r2)); return (num1 * m + num2 * m) / m; } console.log(add(0.1,0.2)); //0.3 console.log(add(0.15,0.2256)); //0.3756
Yang kedua ialah menggunakan kaedah toPrecision() dan toFixed() terbina dalam. Ambil perhatian bahawa rentetan nilai pulangan kaedah .
function add(x, y) { return x.toPrecision() + y.toPrecision() } console.log(add(0.1,0.2)); //"0.10.2"
7 Laksanakan fungsi isInteger(x) untuk menentukan sama ada x ialah integer
Anda boleh menukar x kepada perpuluhan dan menentukan sama ada ia sama dengan. Itu sendiri. JavaScript boleh mewakili dengan tepat ialah Antara -2^53 dan 2^53 (tidak termasuk dua titik akhir), di luar julat ini, nilai tidak boleh diwakili dengan tepat. ES6 memperkenalkan dua pemalar, Number.MAX_SAFE_INTEGER dan Number.MIN_SAFE_INTEGER, untuk mewakili had atas dan bawah julat ini, dan menyediakan Number.isSafeInteger() untuk menentukan sama ada integer ialah integer selamat.
function isInteger(x) { return parseInt(x, 10) === x; }
8 Dalam kod berikut, dalam susunan apakah nombor 1-4 akan dikeluarkan? Mengapa ia keluaran seperti ini?
Number.isInteger(25) // true Number.isInteger(25.0) // true Number.isInteger(25.1) // false Number.isInteger("15") // false Number.isInteger(true) // false
9 Tulis fungsi dengan kurang daripada 80 aksara untuk menentukan sama ada rentetan ialah rentetan palindrom
(function() { console.log(1); setTimeout(function(){console.log(2)}, 1000); setTimeout(function(){console.log(3)}, 0); console.log(4); })();
10 Tulis kaedah jumlah yang boleh berfungsi seperti biasa apabila dipanggil dengan cara berikut
function isPalindrome(str) { str = str.replace(/\W/g, '').toLowerCase(); return (str == str.split('').reverse().join('')); }
11 Jawab soalan berikut berdasarkan coretan kod di bawah
console.log(sum(2,3)); // Outputs 5 console.log(sum(2)(3)); // Outputs 5
function sum() { var fir = arguments[0]; if(arguments.length === 2) { return arguments[0] + arguments[1] } else { return function(sec) { return fir + sec; } } }
Mengklik mana-mana satu daripada 5 butang akan mengeluarkan 5
2. Berikan pelaksanaan yang dijangkakanfor (var i = 0; i < 5; i++) { var btn = document.createElement('button'); btn.appendChild(document.createTextNode('Button ' + i)); btn.addEventListener('click', function(){ console.log(i); }); document.body.appendChild(btn); }
Rujuk IIFE.
12. Apakah yang akan dikeluarkan oleh kod berikut? kenapa? Apakah yang akan dikeluarkan? Anda akan mengetahuinya selepas menjalankannya, dan ia mungkin tidak dijangka.reverse() akan menukar tatasusunan itu sendiri dan mengembalikan rujukan kepada tatasusunan asal. Untuk penggunaan
slice, sila rujuk: slicevar arr1 = "john".split(''); j o h n var arr2 = arr1.reverse(); n h o j var arr3 = "jones".split(''); j o n e s arr2.push(arr3); console.log("array 1: length=" + arr1.length + " last=" + arr1.slice(-1)); console.log("array 2: length=" + arr2.length + " last=" + arr2.slice(-1));
console.log(1 + "2" + "2"); console.log(1 + +"2" + "2"); console.log(1 + -"1" + "2"); console.log(+"1" + "1" + "2"); console.log( "A" - "B" + "2"); console.log( "A" - "B" + 2);
输出什么,自己去运行吧,需要注意三个点:
多个数字和数字字符串混合运算时,跟操作数的位置有关
console.log(2 + 1 + '3'); / /‘33' console.log('3' + 2 + 1); //'321'
数字字符串之前存在数字中的正负号(+/-)时,会被转换成数字
console.log(typeof '3'); // string console.log(typeof +'3'); //number
同样,可以在数字前添加 '',将数字转为字符串
console.log(typeof 3); // number console.log(typeof (''+3)); //string
对于运算结果不能转换成数字的,将返回 NaN
console.log('a' * 'sd'); //NaN console.log('A' - 'B'); // NaN
14、什么是闭包?举例说明
可以参考此篇:从作用域链谈闭包
15、下面的代码会输出什么?为啥?
for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }, i * 1000 ); }
请往前面翻,参考第4题,解决方式已经在上面了
16、解释下列代码的输出
console.log("0 || 1 = "+(0 || 1)); console.log("1 || 2 = "+(1 || 2)); console.log("0 && 1 = "+(0 && 1)); console.log("1 && 2 = "+(1 && 2));
逻辑与和逻辑或运算符会返回一个值,并且二者都是短路运算符:
逻辑与返回第一个是 false 的操作数 或者 最后一个是 true的操作数
console.log(1 && 2 && 0); //0 console.log(1 && 0 && 1); //0 console.log(1 && 2 && 3); //3
如果某个操作数为 false,则该操作数之后的操作数都不会被计算
逻辑或返回第一个是 true 的操作数 或者 最后一个是 false的操作数
console.log(1 || 2 || 0); //1 console.log(0 || 2 || 1); //2 console.log(0 || 0 || false); //false
如果某个操作数为 true,则该操作数之后的操作数都不会被计算
如果逻辑与和逻辑或作混合运算,则逻辑与的优先级高:
console.log(1 && 2 || 0); //2 console.log(0 || 2 && 1); //1 console.log(0 && 2 || 1); //1
在 JavaScript,常见的 false 值:
0, '0', +0, -0, false, '',null,undefined,null,NaN
要注意空数组([])和空对象({}):
console.log([] == false) //true console.log({} == false) //false console.log(Boolean([])) //true console.log(Boolean({})) //true
所以在 if 中,[] 和 {} 都表现为 true:
17、解释下面代码的输出
console.log(false == '0') console.log(false === '0')
18、解释下面代码的输出
var a={}, b={key:'b'}, c={key:'c'}; a[b]=123; a[c]=456; console.log(a[b]); 输出是456。
19、在下面的代码中,数字 1-4 会以什么顺序输出?为什么会这样输出?
(function() { console.log(1); setTimeout(function(){console.log(2)}, 1000); setTimeout(function(){console.log(3)}, 0); console.log(4); })();
这个就不多解释了,主要是 JavaScript 的定时机制和时间循环,不要忘了,JavaScript 是单线程的。详解可以参考 从setTimeout谈JavaScript运行机制。
20、写一个少于 80 字符的函数,判断一个字符串是不是回文字符串
function isPalindrome(str) { str = str.replace(/\W/g, '').toLowerCase(); return (str == str.split('').reverse().join('')); }
这个题我在 codewars 上碰到过,并收录了一些不错的解决方式,可以戳这里:Palindrome For Your Dome
21、写一个按照下面方式调用都能正常工作的 sum 方法
console.log(sum(2,3)); // Outputs 5 console.log(sum(2)(3)); // Outputs 5
针对这个题,可以判断参数个数来实现:
function sum() { var fir = arguments[0]; if(arguments.length === 2) { return arguments[0] + arguments[1] } else { return function(sec) { return fir + sec; } } }
22、解释下面代码的输出,并修复存在的问题
var hero = { _name: 'John Doe', getSecretIdentity: function (){ return this._name; } }; var stoleSecretIdentity = hero.getSecretIdentity; console.log(stoleSecretIdentity()); console.log(hero.getSecretIdentity());
将 getSecretIdentity 赋给 stoleSecretIdentity,等价于定义了 stoleSecretIdentity 函数:
var stoleSecretIdentity = function (){ return this._name; } stoleSecretIdentity
的上下文是全局环境,所以第一个输出 undefined。若要输出 John Doe,则要通过 call 、apply 和 bind 等方式改变 stoleSecretIdentity 的this 指向(hero)。
第二个是调用对象的方法,输出 John Doe。
23、给你一个 DOM 元素,创建一个能访问该元素所有子元素的函数,并且要将每个子元素传递给指定的回调函数。
函数接受两个参数:
DOM
指定的回调函数
原文利用 深度优先搜索(Depth-First-Search) 给了一个实现:
function Traverse(p_element,p_callback) { p_callback(p_element); var list = p_element.children; for (var i = 0; i < list.length; i++) { Traverse(list[i],p_callback); // recursive call } }
相关学习推荐:javascript视频教程