js经典试题之数组与函数
1:列举js的全局函数?
答案:JavaScript 中包含以下 7 个全局函数escape( )、eval( )、isFinite( )、isNaN( )、parseFloat( )、parseInt( )、unescape( )。
注意:serTimeout是window的一个方法(window对象的方法),如果把window当做全局对象来看待的话,它就是全局函数。严格来讲,它不是。
2:深复制与浅复制的区别,以及如何实现?
答案:
浅复制只会将对象的各个属性进行依次复制,并不会进行递归复制,而 JavaScript 存储对象都是存地址的,所以浅复制会导致 obj.arr 和 shallowObj.arr 指向同一块内存地址。
深复制则不同,它不仅将原对象的各个属性逐个复制出去,而且将原对象各个属性所包含的对象也依次采用深复制的方法递归复制到新对象上。
简单的浅复制:复制一份obj1
叫做obj2,
然后把obj2.b
改成100,
但却不小心改到obj1.b,
因为他们根本是同一个对象,这就是所谓的浅拷贝。
var obj1 = { a: 10, b: 20, c: 30 }; var obj2 = obj1; obj2.b = 100; console.log(obj1); // { a: 10, b: 100, c: 30 } <-- b 被改到了 console.log(obj2); // { a: 10, b: 100, c: 30 }
简单的深复制:不会改到原本的obj1。
var obj1 = { a: 10, b: 20, c: 30 }; var obj2 = { a: obj1.a, b: obj1.b, c: obj1.c }; obj2.b = 100; console.log(obj1); // { a: 10, b: 20, c: 30 } <-- b 沒被改到 console.log(obj2); // { a: 10, b: 100, c: 30 }
jquery 有提供一个$.extend
可以用来做 Deep Copy。
var $ = require('jquery'); var obj1 = { a: 1, b: { f: { g: 1 } }, c: [1, 2, 3] }; var obj2 = $.extend(true, {}, obj1); console.log(obj1.b.f === obj2.b.f); // false
3:列举用作javascript异步模式的编程的方法?
答案: 回调函数 事件监听 发布/订阅 Promises对象
解析:
回调函数,这是异步编程最基本的方法。
f1(); f2(); function f1(callback){ setTimeout(function () { // f1的任务代码 callback(); }, 1000); } f1(f2);
事件监听,另一种思路是采用事件驱动模式。任务的执行不取决于代码的顺序,而取决于某个事件是否发生。
f1.on('done', f2); function f1(){ setTimeout(function () { // f1的任务代码 f1.trigger('done'); }, 1000); }
发布/订阅,上一节的"事件",完全可以理解成"信号"。
jQuery.subscribe("done", f2); function f1(){ setTimeout(function () { // f1的任务代码 jQuery.publish("done"); }, 1000); } jQuery.unsubscribe("done", f2);
Promises对象,Promises 对象是CommonJS 工作组提出的一种规范,目的是为异步编程提供统一接口。
f1().then(f2); function f1(){ var dfd = $.Deferred(); setTimeout(function () { // f1的任务代码 dfd.resolve(); }, 500); return dfd.promise; } 指定多个回调函数: f1().then(f2).then(f3); 指定发生错误时的回调函数: f1().then(f2).fail(f3);
4:
5:如何判断一个js对象是否是Array,arr为要判断的对象,其中最准确的方法是?
typeof(arr) arr instanceof Array arr.toString==='[object Array]'; Object.prototype.toString.call(arr) === '[object Array]';
答案:Object.prototype.toString.call(arr) === '[object Array]';
分析:
6:运行以下程序,y和z的最终结果?
var m= 1, j = k = 0; function add(n) { return n = n+1; } y = add(m); function add(n) { return n = n + 3; } z = add(m);
答案:4 4
解析:由于函数声明提升,
所以函数声明会提前,由于存在同名函数,后面的add函数将覆盖第一个add函数
7:语句var arr=[a,b,c,d];执行后,数组arr中每项都是一个整数,下面得到其中最大整数语句正确的是哪几项?
A: Math.max(arr) B: Math.max(arr[0], arr[1], arr[2], arr[3]) C: Math.max.call(Math, arr[0], arr[1], arr[2], arr[3]) D: Math.max.apply(Math,arr)
答案: B C D
解析:
8:以下代码的输出结果是?
var f = function g() { return 23; }; typeof g();
答案:error
解析:
在 JS 里,声明函数只有 2 种方法:
第 1 种: function foo(){...} (函数声明)
第 2 种: var foo = function(){...} (等号后面必须是匿名函数,这句实质是函数表达式)
除此之外,类似于 var foo = function bar(){...} 这样的东西统一按 2 方法处理,即在函数外部无法通过 bar 访问到函数,因为这已经变成了一个表达式。
但为什么不是 "undefined"?
这里如果求 typeof g ,会返回 undefined,但求的是 g(),所以会去先去调用函数 g,这里就会直接抛出异常,所以是 Error。
9:假设 output 是一个函数,输出一行文本。下面的语句输出结果是什么?
output(typeof (function() {output(“Hello World!”)})());
答案:Hello World undefined
解析:
(一):匿名函数如果改为不是立即执行的
output(typeof function() {output('Hello World!')})
输出:‘function’
10、下面关于块内声明函数的做法哪些是正确的?
A、if (x) { function foo() {}} B、if (x) { var foo = function() {}} C、if (x) { foo = function() {}}
答案:B
解析:不要在块内声明一个函数(严格模式会报语法错误)。如果确实需要在块中定义函数,可以使用函数表达式来声明函数。
11、以下函数运行结果为:
(function() { var x=foo(); var foo=function foo() { return “foobar” }; return x; })();
答案:TypeError: foo is not a function
解析:
12、下面这段javascript代码,输出的是?
var msg='hello'; for (var i=0; i<10; i++) { var msg='hello'+i*2+i; } alert(msg);
我的错误答案: “hello”。我以为for循环内部重新定义msg会将其改为局部变量。注意这里只是for循环不是函数。
正确答案:“hello189”
解析:javascript只有函数域,没有块作用域的概念,所以在同一个作用域中同一个变量声明多次还是第一次声明那个!
(一)如果代码改为如下情况:
var msg='hello'; function aa() { for (var i=0; i<10; i++) { var msg='hello'+i*2+i; } } aa() alert(msg);
此时msg在函数中重新声明为局部变量,所以会输出“hello”。
(二):如果将变量用let定义
let msg='hello'; for (let i=0; i<10; i++) { let msg='hello'+i*2+i; } console.log(msg);
输出“hello”。
let msg='hello'; function aa() { for (let i=0; i<10; i++) { let msg='hello'+i*2+i; } } aa() console.log(msg);
输出“hello”。
13、下面这段javascript代码,输出的是?
[1,2,5,10].sort()
答案: 1,10,2,5
解析:
sort()函数在默认情况下使用字母数字(字符串Unicode码点)排序。
要正确的排序一个数组, 你可以用如下代码,很简单的解决方案, 前提是你得知道有这么个坑。
[1,2,5,10].sort(function(a, b){return a-b})
如果需要降序的话:
[1,2,5,10].sort(function(a, b){return b-a})