一、数组模块:
1、找出元素 item 在给定数组 arr 中的位置
如果数组中存在 item,则返回元素在数组中的位置,否则返回 -1复制代码
示例1
输入 [ 1, 2, 3, 4 ], 3
输出 2
function indexOf(arr, item) { return arr.indexOf(item);}复制代码
2、数组求和
计算给定数组 arr 中所有元素的总和:数组中的元素均为 Number 类型
input [ 1, 2, 3, 4 ]
output 10
不考虑算法复杂度,用递归做:function sum(arr) { var len = arr.length; if(len == 0){ return 0; } else if (len == 1){ return arr[0]; } else { return arr[0] + sum(arr.slice(1)); }}常规循环:function sum(arr) { var s = 0; for (var i=arr.length-1; i>=0; i--) { s += arr[i]; } return s;}函数式编程 map-reduce:function sum(arr) { return arr.reduce(function(prev, curr, idx, arr){ return prev + curr; });}forEach遍历:function sum(arr) { var s = 0; arr.forEach(function(e) { s += e; }) return s;};eval:function sum(arr) { return eval(arr.join("+"));};复制代码
3、移除数组中的元素
移除数组 arr 中的所有值与 item 相等的元素。不要直接修改数组 arr,结果返回新的数组
输入 [1, 2, 3, 4, 2], 2
输出 [1, 3, 4]
function remove(arr, item) { //声明一个新数组保存结果 var a = []; //循环遍历 for(var i=0; i < arr.length; i++){ //如果arr[i]不等于item,就加入数组a if(arr[i] != item){ a.push(arr[i]); } } return a; }复制代码
移除数组 arr 中的所有值与 item 相等的元素,直接在给定的 arr 数组上进行操作,并将结果返回
输入 [1, 2, 2, 3, 4, 2, 2], 2
输出 [1, 3, 4]
function removeWithoutCopy(arr, item) { for(var i = 0;i<arr.length;i++){ if(arr[i] == item){ arr.splice(i,1);//从数组的第i个位置开始,删除后一个元素 i--;//因为他是直接删除的,那个下标会改变的,所以要自减 } } return arr} removeWithoutCopy([1, 2, 2, 4, 2, 2], 2);1.splice()function remove(arr,item){ for(var i=0;i<newarr.length;i++){ if(newarr[i] == item){ newarr.splice(i,1); } } return newarr;} 2.push()function remove(arr,item){ var newarr = []; for(var i=0;i<arr.length;i++){ if(arr[i] != item){ newarr.push(arr[i]); } } return newarr;}function remove(arr,item){ var newarr = []; for(var i=0;i<arr.length;i++){ if(arr[i] == item)continue; newarr.push(arr[i]); } return nawarr;}3.Arra y.prototype.filter()function remove(arr,item){ return arr.filter(function(ele){ return ele != item; })}复制代码
4、 添加元素
在数组 arr 末尾添加元素 item。不要直接修改数组 arr,结果返回新的数组
输入 [1, 2, 3, 4], 10
输出 [1, 2, 3, 4, 10]
function append(arr, item) { var a=[]; for(var i=0;i<arr.length;i++){ a.push(arr[i]); } a.push(item); return a;}append([1, 2, 3, 4], 10);复制代码
在数组 arr 的 index 处添加元素 item。不要直接修改数组 arr,结果返回新的数组
输入 [1, 2, 3, 4], 'z', 2
输出 [1, 2, 'z', 3, 4]
//利用slice+concatfunction insert(arr, item, index) { return arr.slice(0,index).concat(item,arr.slice(index));}//利用concat +splicefunction insert(arr, item, index) { var newArr=arr.concat(); newArr.splice(index,0,item); return newArr;}//利用slice+splicefunction insert(arr, item, index) { var newArr=arr.slice(0); newArr.splice(index,0,item); return newArr;}//利用push.apply+splicefunction insert(arr, item, index) { var newArr=[]; [].push.apply(newArr, arr); newArr.splice(index,0,item); return newArr;}//普通的迭代拷贝function insert(arr, item, index) { var newArr=[]; for(var i=0;i<arr.length;i++){ newArr.push(arr[i]); } newArr.splice(index,0,item); return newArr;}复制代码
5、删除数组最后一个元素
删除数组 arr 最后一个元素。不要直接修改数组 arr,结果返回新的数组
输入 [1, 2, 3, 4]
输出 [1, 2, 3]
function truncate(arr) { var newArr=arr.slice(0)//slice() 方法可提取字符串的某个部分,并以新的字符串返回被提取的部分。//语法 stringObject.slice(start,end) newArr.pop()//pop() 方法用于删除并返回数组的最后一个元素。 return newArr}复制代码
6.删除数组第一个元素
删除数组 arr 第一个元素。不要直接修改数组 arr,结果返回新的数组
输入 [1, 2, 3, 4]
输出 [2, 3, 4]
function curtail(arr) {
var a = arr.slice(0)
a.shift()
return a
}
复制代码
7、数组合并
合并数组 arr1 和数组 arr2。不要直接修改数组 arr,结果返回新的数组
输入 [1, 2, 3, 4], ['a', 'b', 'c', 1]
输出 [1, 2, 3, 4, 'a', 'b', 'c', 1]
//利用concatfunction concat(arr1, arr2) { return arr1.concat(arr2);}//利用slice+push.applyfunction concat(arr1, arr2) { var newArr=arr1.slice(0); [].push.apply(newArr, arr2); return newArr;}//利用slice+pushfunction concat(arr1, arr2) { var newArr=arr1.slice(0); for(var i=0;i<arr2.length;i++){ newArr.push(arr2[i]); } return newArr;}//普通的迭代拷贝function concat(arr1, arr2) { var newArr=[]; for(var i=0;i<arr1.length;i++){ newArr.push(arr1[i]); } for(var j=0;j<arr2.length;j++){ newArr.push(arr2[j]); } return newArr;}复制代码
8、计数
统计数组 arr 中值等于 item 的元素出现的次数
输入 [1, 2, 4, 4, 3, 4, 3], 4
输出 3
//filter()-->利用指定的函数确定是否在返回的数组中包含某一项
function count(arr, item) {
var count = arr.filter(function(a) {
return a === item; //返回true的项组成的数组
});
return count.length;
}
//map()-->对数组中的每一项进行给定函数,
//返回每次函数条用的结果组成的数组;
function count(arr, item) {
var count = 0;
arr.map(function(a) {
if(a === item) {
count++;
}
});
return count;
}
//for循环
function count(arr, item) {
var count = 0;
for(var i=0; i<arr.length; i++) {
if(arr[i] === item) {
count++;
}
}
return count;
}
//reduce()-->从数组的第一项开始,逐个遍历到最后;
function count(arr, item) {
var count = arr.reduce(function(prev, curr) {
return curr === item ? prev+1 : prev;
}, 0);
return count;
}
//forEach()-->对数组中的每一项运行传入的函数
function count(arr, item) {
var count = 0;
arr.forEach(function(a) {
a === item ? count++ : 0;
});
return count;
}
复制代码
9、查找重复元素
找出数组 arr 中重复出现过的元素
输入 [1, 2, 4, 4, 3, 3, 1, 5, 3]
输出 [1, 3, 4]
function duplicates(arr) {
var a=arr.sort(),b=[];
for(var i in a){
if(a[i]==a[i-1] && b.indexOf(a[i])==-1)
b.push(a[i]);
}
return b;
}//先排序,如果后一个与前一个相等且未保存,则保存。
复制代码
10、 求二次方
为数组 arr 中的每个元素求二次方。不要直接修改数组 arr,结果返回新的数组
输入 [1, 2, 3, 4]
输出 [1, 4, 9, 16]
// 1
function square(arr) {
var a = arr.slice(0)
a = a.map(function(val) {
return val*val
})
return a
}
function square(arr) {
var newarr = arr.slice(0);
//复制一个arr数组
for (var i=0;i<newarr.length;i++){
newarr[i]= newarr[i]* newarr[i];
}
return newarr;
}
// 2
function square(arr) {
return arr.map(function(item,index,array){
return item*item;
})
}
//3
function square(arr) {
//声明一个新的数组存放结果
var a = [];
arr.forEach(function(e){
//将arr中的每一个元素求平方后,加入到a数组中
a.push(e*e);
});
return a;
}
复制代码
11、查找元素位置
在数组 arr 中,查找值与 item 相等的元素出现的所有位置
输入 'abcdefabc'
输出 [0, 6]
//filter
function findAllOccurrences(arr, target) {
var result=[];
arr.filter(function(item,index){
return item===target&&result.push(index);
});
return result;
}
//for
function findAllOccurrences(arr, target) {
var result=[];
for(var i=0;i<arr.length;i++){
if(arr[i]===target){
result.push(i);
}
}
return result;
}
//lastIndexOf+slice/splice
function findAllOccurrences(arr, target) {
var result=[],index=arr.lastIndexOf(target);
while(index>-1){
result.push(index);
arr.splice(index,1);//arr=arr.slice(0,index);
index=arr.lastIndexOf(target);
}
return result;
}
//indexOf
function findAllOccurrences(arr, target) {
var result=[],index=arr.indexOf(target);
while(index>-1){
result.push(index);
index=arr.indexOf(target,index+1);
}
return result;
}
复制代码
二、函数部分 :
1、避免全局变量
function globals() {
var myObject = { //这里需要加 var let等关键字
name : 'Jory'
};
return myObject;
}
复制代码
2、正确的定义函数
请修复给定的 js 代码中,函数定义存在的问题
输入 true
输出 a
//源码
function functions(flag) {
if (flag) {
function getValue() { return 'a'; }
} else {
function getValue() { return 'b'; }
}
return getValue();
}
// 改正后的
function functions(flag) {
if (flag) {
var getValue =function() { return 'a'; }
} else {
var getValue =function() { return 'b'; }
}
return getValue();
}
functions(true);
复制代码
3、判断两个数是否相等
判断 val1 和 val2 是否完全等同
function identity(val1, val2) {
if(val1===val2) {
return true;
}else{
return false
}
}
// 以后就简写装逼
function identity(val1, val2) {
if(val1===val2)return true;
else return false;
}
/*
一般使用双等来判断(==),如果还需要类型相同那么就用三等(===)。
说一下这两个的区别:
== equality 等同,=== identity 恒等。
==, 两边值类型不同的时候,要先进行类型转换,再比较。
==,不做类型转换,类型不同的一定不等。
下面分别说明:
先说 ===,这个比较简单。下面的规则用来判断两个值是否===相等:
1、如果类型不同,就[不相等]
2、如果两个都是数值,并且是同一个值,那么[相等]。
3、如果两个都是字符串,每个位置的字符都一样,那么[相等];否则[不相等]。
4、如果两个值都是true,或者都是false,那么[相等]。
5、如果两个值都引用同一个对象或函数,那么[相等];否则[不相等]。
6、如果两个值都是null,或者都是undefined,那么[相等]。
再说 ==,根据以下规则:
1、如果两个值类型相同,进行 === 比较。
2、如果两个值类型不同,他们可能相等。根据下面规则进行类型转换再比较:
a、如果一个是null、一个是undefined,那么[相等]。
b、如果一个是字符串,一个是数值,把字符串转换成数值再进行比较。
c、如果任一值是 true,把它转换成 1 再比较;如果任一值是 false,把它转换成 0 再比较。
d、任何其他组合,都[不相等]。
*/
复制代码
4、计时器
实现一个打点计时器,要求 1、从 start 到 end(包含 start 和 end),每隔 100 毫秒 console.log 一个数字,每次数字增幅为 1 2、返回的对象中需要包含一个 cancel 方法,用于停止定时操作 3、第一个数需要立即输出
function count(start, end) {
//立即输出第一个值
console.log(start++);
var timer = setInterval(function(){
if(start <= end){
console.log(start++);
}else{
clearInterval(timer);
}
},100);
//返回一个对象
return {
cancel : function(){
clearInterval(timer);
}
};
}
复制代码
5、流程控制
实现 fizzBuzz 函数,参数 num 与返回值的关系如下: 1、如果 num 能同时被 3 和 5 整除,返回字符串 fizzbuzz 2、如果 num 能被 3 整除,返回字符串 fizz 3、如果 num 能被 5 整除,返回字符串 buzz 4、如果参数为空或者不是 Number 类型,返回 false 5、其余情况,返回参数 num
输入: 15
输出: fizzbuzz
function fizzBuzz(num) { if(num%3 == 0 && num%5 == 0) return "fizzbuzz"; else if(num%3 == 0) return "fizz"; else if(num%5 == 0) return "buzz"; else if(num == null || typeof num != "number") return false; else return num;}//又一方法function fizzBuzz(num) { var a = num % 3; var b = num % 5; if (a == 0 && b == 0) { return 'fizzbuzz'; } else if (a == 0) { return 'fizz' } else if (b == 0) { return 'buzz' } else if (num == 'null' || typeof (num) != 'number') { return false } else { return num }}复制代码
6、 函数传参
将数组 arr 中的元素作为调用函数 fn 的参数
输入:function (greeting, name, punctuation) {
return greeting + ', ' + name + (punctuation || '!');
}, ['Hello', 'Ellie', '!']
输出:Hello, Ellie!
//调用函数可以使用call或者apply这两个方法,区别在于call需要将传递给函数的参数明确写出来,是多少参数就需要写多少参数。而apply则将传递给函数的参数放入一个数组中,传入参数数组即可。
function argsAsArray(fn, arr) {
return fn.apply(this, arr)
}
// 调用函数的三种方式
obj.func();
func.call(obj,args);//参数列出
func.apply(obj,[m,n......]);//参数数组
复制代码
7、函数的上下文
将函数 fn 的执行上下文改为 obj 对象
输入:function () {return this.greeting + ', ' + this.name + '!!!';}, {greeting: 'Hello', name: 'Rebecca'}
输出:Hello, Rebecca!!!
//在JavaScript中,函数是一种对象,其上下文是可以变化的,对应的,函数内的this也是可以变化的,函数可以作为一个对象的方法,也可以同时作为另一个对象的方法,可以通过Function对象中的call或者apply方法来修改函数的上下文,函数中的this指针将被替换为call或者apply的第一个参数。将函数 fn 的执行上下文改为 obj 对象,只需要将obj作为call或者apply的第一个参数传入即可。
function speak(fn, obj) {
return fn.apply(obj, obj);
}
复制代码
8、返回函数
实现函数 functionFunction,调用之后满足如下条件: 1、返回值为一个函数 f 2、调用返回的函数 f,返回值为按照调用顺序的参数拼接,拼接字符为英文逗号加一个空格,即 ', ' 3、所有函数的参数数量为 1,且均为 String 类型
输入:functionFunction('Hello')('world')
输出:Hello, world
//首先执行functionFunction('Hello'),传入参数str,然后返回函数f,f与('world')组合,执行f('world'),传入参数s,f返回str+", "+s,即Hello, world。注意中间的逗号后面有一个空格。
function functionFunction(str) {
var f = function(s){
return str+", "+s;
}
return f;
}
复制代码
9、使用闭包
实现函数 makeClosures,调用之后满足如下条件: 1、返回一个函数数组 result,长度与 arr 相同 2、运行 result 中第 i 个函数,即 resulti,结果与 fn(arr[i]) 相同
输入:[1, 2, 3], function (x) { return x * x; }
输出:4
function makeClosures(arr, fn) {
var result = [];
arr.forEach(function (obj) {
result.push(function () {
return fn(obj);
})
});
return result;
}
//es6的
function makeClosures(arr, fn) {
var result = new Array();
for(let i=0;i<arr.length;i++){
result[i] = function(){
return fn(arr[i]); //let声明的变量只在let所在代码块内有效,因此每次循环的i都是一个新的变量
};
}
return result;
}
//es5的
//这种是错误的写法会导致result中每个函数的参数都是arr[arr.length]
function makeClosures(arr, fn) {
var result = new Array();
for(var i=0;i<arr.length;i++){
result[i] = function(){
return fn(arr[i]);
};
}
return result;
}
//参考《JavaScript高级程序设计》的典型方法
function makeClosures(arr, fn) {
var result = new Array();
for(var i=0;i<arr.length;i++){
result[i] = function(num){
return function(){
return fn(num);
}
}(arr[i]);
}
return result;
}
//使用ES5的bind()方法
function makeClosures(arr, fn) {
var result = new Array();
for(var i=0;i<arr.length;i++){
result[i] = fn.bind(null,arr[i]);
}
return result;
}
//使用forEach()
function makeClosures(arr, fn) {
var result = new Array();
arr.forEach(function(curr){
result.push(function(){return fn(curr)});
})
return result;
}
复制代码
10、二次封装函数
已知函数 fn 执行需要 3 个参数。请实现函数 partial,调用之后满足如下条件: 1、返回一个函数 result,该函数接受一个参数 2、执行 result(str3) ,返回的结果与 fn(str1, str2, str3) 一致
输入:var sayIt = function(greeting, name, punctuation) { return greeting + ', ' + name + (punctuation || '!'); }; partial(sayIt, 'Hello', 'Ellie')('!!!');
输出:Hello, Ellie!!!
// call和apply必须显式地调用str3,立即执行// bind不是立即执行,未传入str3时,并未执行,只是返回一个函数,等待参数传入// this用于上下文不确定的情况 // callfunction partial(fn, str1, str2) { function result(str3) { return fn.call(this, str1, str2, str3); } return result;} // apply(这里只是为了对照)function partial(fn, str1, str2) { function result(str3) { return fn.apply(this, [str1, str2, str3]); } return result;} // 这个bind会生成一个新函数(对象), 它的str1, str2参数都定死了, str3未传入, 一旦传入就会执行function partial(fn, str1, str2) { return fn.bind(this, str1, str2); // 或 return fn.bind(null, str1, str2);} // bind同上, 多了一步, 把str3传入的过程写在另一个函数里面,// 而另一个函数也有str1, str2参数// 此法有种多次一举的感觉,但是表示出了后续的调用。function partial(fn, str1, str2) { function result(str3) { return fn.bind(this, str1, str2)(str3); } return result;} // 匿名函数,默认this绑定global,与bind的第一个参数为this时效果一样。function partial(fn, str1, str2) { return function(str3) { return fn(str1, str2, str3); }} // ES6。this指向undefined.const partial = (fn, str1, str2) => str3 => fn(str1, str2, str3);复制代码
实现函数 partialUsingArguments,调用之后满足如下条件: 1、返回一个函数 result 2、调用 result 之后,返回的结果与调用函数 fn 的结果一致 3、fn 的调用参数为 partialUsingArguments 的第一个参数之后的全部参数以及 result 的调用参数
输入:无
输出:无
// ****类似与11题*****
//arguments不能用slice方法直接截取,需要先转换为数组,var args = Array.prototype.slice.call(arguments);合并参数可以使用concat方法,并且也需要将arguments先转换为数组才能使用concat进行合并。最用使用apply执行传入的函数即可。
function partialUsingArguments(fn) {
//先获取p函数第一个参数之后的全部参数
var args = Array.prototype.slice.call(arguments,1);
//声明result函数
var result = function(){
//使用concat合并两个或多个数组中的元素
return fn.apply(null, args.concat([].slice.call(arguments)));
}
return result;
}
复制代码
11、使用arguments
函数 useArguments 可以接收 1 个及以上的参数。请实现函数 useArguments,返回所有调用参数相加后的结果。本题的测试参数全部为 Number 类型,不需考虑参数转换。
输入:1, 2, 3, 4
输出:10
function useArguments() {
/*
因为参数数量不定,可以先获取参数个数arguments.length
然后循环求值
*/
//声明一个变量保存最终结果
var sum = 0;
//循环求值
for(var i = 0; i < arguments.length; i++){
sum += arguments[i];
}
return sum;
}
console.log(useArguments(1,2,3,4));//output 10
复制代码
12、使用apply 调用函数
实现函数 callIt,调用之后满足如下条件 1、返回的结果为调用 fn 之后的结果 2、fn 的调用参数为 callIt 的第一个参数之后的全部参数
输入:无
输出:无
//因为arguments并非真正的数组,因此要获得callIt的第一个参数之后的所有参数,不能直接使用slice方法截取,需要先将arguments转换为真正的数组才行。有两种常见的方法,一是使用slice方法:var args = Array . prototype . slice . call ( arguments );二是循环遍历逐一填入新数组。在获得了args之后,就可以调用apply来执行传入的函数参数。function callIt(fn) { //将arguments转化为数组后,截取第一个元素之后的所有元素 var args = Array.prototype.slice.call(arguments,1); //调用fn var result = fn.apply(null,args);//因为调用calllt的第一个参数之后的全部参数,所以这里是null return result;}复制代码
13、柯里化
柯里化有3个常见作用: 1. 参数复用 ;2. 提前返回;3. 延迟计算/运行
已知 fn 为一个预定义函数,实现函数 curryIt,调用之后满足如下条件: 1、返回一个函数 a,a 的 length 属性值为 1(即显式声明 a 接收一个参数) 2、调用 a 之后,返回一个函数 b, b 的 length 属性值为 1 3、调用 b 之后,返回一个函数 c, c 的 length 属性值为 1 4、调用 c 之后,返回的结果与调用 fn 的返回值一致 5、fn 的参数依次为函数 a, b, c 的调用参数
输入:var fn = function (a, b, c) {return a + b + c};
curryIt(fn)(1)(2)(3);
输出:6
function curryIt(fn) { return a = function(d){ var b1 = arguments[0]; return b = function(f){ var c1 = arguments[0]; return c = function(g){ var a1 = arguments[0]; return fn.call(this,d,f,g); } } }}//柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。简单理解题目意思,就是指,我们将预定义的函数的参数逐一传入到curryIt中,当参数全部传入之后,就执行预定义函数。于是,我们首先要获得预定义函数的参数个数fn.length,然后声明一个空数组去存放这些参数。返回一个匿名函数接收参数并执行,当参数个数小于fn.length,则再次返回该匿名函数,继续接收参数并执行,直至参数个数等于fn.length。最后,调用apply执行预定义函数。function curryIt(fn) { //获取fn参数的数量 var n = fn.length; //声明一个数组args var args = []; //返回一个匿名函数 return function(arg){ //将curryIt后面括号中的参数放入数组 args.push(arg); //如果args中的参数个数小于fn函数的参数个数, //则执行arguments.callee(其作用是引用当前正在执行的函数,这里是返回的当前匿名函数)。 //否则,返回fn的调用结果 if(args.length < n){ return arguments.callee; }else return fn.apply("",args); } }复制代码
三、逻辑运算:
1、或运算
返回参数 a 和 b 的逻辑或运算结果
输入:false, true
输出:true
function or(a, b) { if(a||b) return true; else return false;}复制代码
2、且运算
返回参数a 和 b 的逻辑且运算结果
输入:false, true
输出: false
functino add(a,b){ return a&&b;}复制代码
四、其它部分:
1、模块
完成函数 createModule,调用之后满足如下要求: 1、返回一个对象 2、对象的 greeting 属性值等于 str1, name 属性值等于 str2 3、对象存在一个 sayIt 方法,该方法返回的字符串为 greeting属性值 + ', ' + name属性值
声明对象有两种常见的方式:var obj = {};和var obj = new Object();。前面一种可以直接在括号中以key:value的方式定义属性,后一种采用点运算符给对象添加属性。function createModule(str1, str2) { var obj = { greeting : str1, name : str2, sayIt : function(){ //两个属性前面都需要加上this return this.greeting+", "+this.name; } }; return obj; } console.log(createModule("11","22"))//{greeting: "11", name: "22", sayIt: ƒ}复制代码
2、二进制转换
获取数字 num 二进制形式第 bit 位的值。注意: 1、bit 从 1 开始 2、返回 0 或 1 3、举例:2 的二进制为 10,第 1 位为 0,第 2 位为 1
输入:128,8
输出:1
通过num.toString(2)能直接将num转换为2进制数格式的字符串,利用下标就能将对应值取出来。题目返回的数字是从右往左,因此下标为倒数。
function valueAtBit(num, bit) {
var s = num.toString(2);
console.log(s);//1000 0000
console.log(s.length)//8
return s[s.length - bit];
}
console.log(valueAtBit(128,8))//1
复制代码
给定二进制字符串,将其换算成对应的十进制数字
输入:'11000000'
输出:192
parseInt方法可以将其它进制转换为十进制,只需要给该方法传入需要转换的字符串和该字符串的进制表示两个参数即可。
function base10(str) {
/**
其它进制转十进制
parseInt(str,2)
parseInt(str,8)
parseInt(str,16)
*/
return parseInt(str,2);
}
console.log(base10('11000000'))//192
复制代码
将给定数字转换成二进制字符串。如果字符串长度不足 8 位,则在前面补 0 到满8位。
输入:65
输出:01000001
function convertToBinary(num) {
var s = num.toString(2);
while(s.length<8){
s = '0'+s;
}
return s;
}
//首先通过toString方法将num转为2进制数形式,然后判断其长度是否足够8位。如不足8位,则声明一个“0000000”字符串用于补0,因为目标的2进制数形式最少为一位,因此最多只需要7个0;通过slice方法对“0000000”进行截取,然后将其结果加在目标前面即可。
function convertToBinary(num) {
//转换为2进制格式
var s = num.toString(2);
//获得2进制数长度
if( s.length<8){
//声明一个字符串用于补满0
var s1 = "0000000";
var s2 = s1.slice(0,8-l);
s = s2+s;
}
return s;
}
复制代码
3、乘法
求 a 和 b 相乘的值,a 和 b 可能是小数,需要注意结果的精度问题
输入:3, 0.0001
输出:0.0003
// 1
function multiply(a, b) {
return a*b*10000*10000/10000/10000
}
// 2
//根据两个书中精度较高的一个来确定,先将其转换成字符串,然后根据小数点的位置确定小数位数,
//字符串长度减去‘.'的位置后还要再减去1得到正确的小数位数,两个取其大,然后用toFixed()函数确定 //结果的小数位数
function multiply(a, b) {
//求两个数中精度大的一个
var stra=a.toString();
var strb=b.toString();
var len=Math.max(stra.length-stra.indexOf('.')-1,strb.length-strb.indexOf('.')-1);
//
return parseFloat(a*b).toFixed(len);
}
// 3
//通过将a、b小数位数的相加,能够得到a*b结果的小数位数最大可能值。然后使用toFixed方法可以将结果的小数位数指定为可能的最大值,即保证了结果的精度。但本题实际上,仅返回a*b也能通过。在浏览器上做实验,最大17位的小数位数满足了该题全部的测试用例。
function multiply(a, b) {
return a*b;
}
复制代码
4、改变上下文
将函数 fn 的执行上下文改为 obj,返回 fn 执行后的值
输入:alterContext(function() {return this.greeting + ', ' + this.name + '!'; }, {name: 'Rebecca', greeting: 'Yo' })
输出:Yo, Rebecca!
//主要有三种答案。
function alterContext(fn, obj) {
return fn.bind(obj)();//.bind()返回的是一个函数,所以需要立即执行。 }
function alterContext(fn, obj) {
return fn.call(obj);
}
function alterContext(fn, obj) {
return fn.apply(obj);
}
//在JavaScript中,函数是一种对象,其上下文是可以变化的,对应的,函数内的this也是可以变化的,函数可以作为一个对象的方法,也可以同时作为另一个对象的方法,可以通过Function对象中的call或者apply方法来修改函数的上下文,函数中的this指针将被替换为call或者apply的第一个参数。将函数 fn 的执行上下文改为 obj 对象,只需要将obj作为call或者apply的第一个参数传入即可。
function alterContext(fn, obj) {
return fn.call(obj,obj);
}
复制代码
5、批量改变对象属性 ( 涉及原型链问题 )
给定一个构造函数 constructor,请完成 alterObjects 方法,将 constructor 的所有实例的 greeting 属性指向给定的 greeting 变量。
输入:var C = function(name) {this.name = name; return this;}; var obj1 = new C('Rebecca'); alterObjects(C, 'What's up'); obj1.greeting;
输出:What's up
//这是原型链问题。访问一个对象的方法或者是属性,首先会在该对象中寻找,如果找到则返回,如果没找到,则在其原型链上面向上寻找,直至基原型,如还未找到,则返回undefined。将 constructor 的所有实例的 greeting 属性指向给定的 greeting 变量,只需要在constructor的原型上面添加greeting属性,并指定值。
function alterObjects(constructor, greeting) {
//添加prototype的作用就是添加一个公共方法,或者公共属性
constructor.prototype.greeting = greeting;
}
复制代码
6、属性遍历
找出对象 obj 不在原型链上的属性(注意这题测试例子的冒号后面也有一个空格~) 1、返回数组,格式为 key: value 2、结果数组不要求顺序
输入:var C = function() {this.foo = 'bar'; this.baz = 'bim';}; C.prototype.bop = 'bip'; iterate(new C());
输出:["foo: bar", "baz: bim"]
//可以使用for-in来遍历对象中的属性,hasOwnproperty方法能返回一个布尔值,指出一个对象是否具有指定名称的属性。此方法无法检查该对象的原型链中是否具有该属性,该属性必须为对象本身的属性。
function iterate(obj) {
var arr = [];
//使用for-in遍历对象属性
for(var key in obj){
//判断key是否为对象本身的属性
if(obj.hasOwnProperty(key)){
//将属性和值按格式存入数组
arr.push(key+": "+obj[key]);
}
}
return arr;
}
复制代码
7、判断是否包含数字(涉及正则表达式)
给定字符串 str,检查其是否包含数字,包含返回 true,否则返回 false
输入:'abc123'
输出:true
// 方法一
//判断字符串中是否含有数字,可以用正则表达式。/\d/可以匹配字符串中的数字字符,用test方法可以检测。
function containsNumber(str) {
var b = /\d/;
return b.test(str);
}
//方法二
function containsNumber(str) {
for(var i=0 ; i<str.length ; i++){
if(str[i] > '0' && str[i] < '9'){
return true;
}
}
return false;
}
复制代码
8、检查重复字符串(正则表达式)
给定字符串 str,检查其是否包含连续重复的字母(a-zA-Z),包含返回 true,否则返回 false
输入:'rattler'
输出:true
在正则表达式中,利用()进行分组,使用斜杠加数字表示引用,\1就是引用第一个分组,\2就是引用第二个分组。将[a-zA-Z]做为一个分组,然后引用,就可以判断是否有连续重复的字母。
function containsRepeatingLetter(str)
return /([a-zA-Z])\1/.test(str);
复制代码
9、判断是否以元音字母结尾(正则表达式)
给定字符串 str,检查其是否以元音字母结尾 1、元音字母包括 a,e,i,o,u,以及对应的大写 2、包含返回 true,否则返回 false
输入:'gorilla'
输出:true
//首先确定元音集合[a,e,i,o,u],然后是以元音结尾,加上$,最后通配大小写,加上i。因此正则表达式为:/[a,e,i,o,u]$/i,最后用test方法去检测字符串str
function endsWithVowel(str) {
return /[a,e,i,o,u]$/i.test(str);
}
复制代码
10、获取指定字符串(正则表达式)
给定字符串 str,检查其是否包含 连续3个数字 1、如果包含,返回最新出现的 3 个数字的字符串 2、如果不包含,返回 false
输入:'9876543'
输出:987
function captureThreeNumbers(str) {
//声明一个数组保存匹配的字符串结果
var arr = str.match(/\d{3}/);
//如果arr存在目标结果,则返回第一个元素,即最早出现的目标结果
if(arr)
return arr[0];
else return false;
}
//题目描述有问题,实际考察的是字符串中是否含有连续的三个任意数字,而不是三个连续的数字。依题,若存在连续的三个任意数字,则返回最早出现的三个数字,若不存在,则返回false。因此需要用到match方法,match()返回的是正则表达式匹配的字符串数组,连续的三个任意数字用正则表达式表示为/\d{3}/。
function captureThreeNumbers(str) {
//声明一个数组保存匹配的字符串结果
var arr = str.match(/\d{3}/);
//如果arr存在目标结果,则返回第一个元素,即最早出现的目标结果
if(arr)
return arr[0];
else return false;
}
复制代码
11、判断是否符合指定格式 (正则表达式)
给定字符串 str,检查其是否符合如下格式 1、XXX-XXX-XXXX 2、其中 X 为 Number 类型
输入:'800-555-1212'
输出:true
//本题需要注意格式,开头^和结尾$必须加上来限定字符串,3个数可表示为\d{3},4个数则为\d{4},{n}表示前面内容出现的次数。正则表达式可写作/^\d{3}-\d{3}-\d{4}$/,有相同部分\d{3}-,因此也可写作/^(\d{3}-){2}\d{4}$/
function matchesPattern(str) {
return/^(\d{3}-){2}\d{4}$/.test(str);
}
复制代码
12、判断是否符合 USD 格式 (正则表达式)
给定字符串 str,检查其是否符合美元书写格式
1、以 $ 开始
2、整数部分,从个位起,满 3 个数字用 , 分隔
3、如果为小数,则小数部分长度为 2
4、正确的格式如:$1,023,032.03 或者 $2.03,错误的格式如:$3,432,12.12 或者 $34,344.3
输入:'$20,933,209.93'
输出:true
复制代码
//本题注意点有必须是USD格式,以$开头,数字结尾,$和小数点的转义。
首先,开头必是$,而正则表达式中$表示结尾,需要进行转义,因此开头为^\$
然后$后必然接数字,并且最少一位,最多三位数,可用{m,n}表示,最少m位,最多n位,因此此段为\d{1,3}
接着,后面如还有数,则必然有,分隔,并且后面必有3个数,类似于,XXX的格式会出现0或者n次,因此此段可表示为(,\d{3})*
最后,如有小数部分,则注意对小数点进行转义,此段可表示为(\.\d{2})?
因此,最后的正则表达式为/^\$\d{1,3}(,\d{3})*(\.\d{2})?$/
使用test方法去检测str
function isUSD(str) {
return /^\$\d{1,3}(,\d{3})*(\.\d{2})?$/.test(str);
}
复制代码
上述题目太多源于网络,仅用于学习。