编程题:JS-计数、流程语句、函数等
文章目录
1.计数
- 实现一个打点计时器,要求
1、从 start 到 end(包含 start 和 end),每隔 100 毫秒 console.log 一个数字,每次数字增幅为 1
2、返回的对象中需要包含一个 cancel 方法,用于停止定时操作
3、第一个数需要立即输出 - 转载:husan
function count(start, end) {
if(start <= end){
console.log(start);
start++;
st = setTimeout(function(){count(start, end)}, 100);
}
return {
cancel: function(){clearTimeout(st);}
}
}
2.流程控制
- 实现 fizzBuzz 函数,参数 num 与返回值的关系如下:
1、如果 num 能同时被 3 和 5 整除,返回字符串 fizzbuzz
2、如果 num 能被 3 整除,返回字符串 fizz
3、如果 num 能被 5 整除,返回字符串 buzz
4、如果参数为空或者不是 Number 类型,返回 false
5、其余情况,返回参数 num
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;
}
}
3.函数
3.1 函数传参
- 将数组 arr 中的元素作为调用函数 fn 的参数
- 示例:
- 转载-希留:调用函数可以使用call或者apply这两个方法,区别在于call需要将传递给函数的参数明确写出来,是多少参数就需要写多少参数。而apply则将传递给函数的参数放入一个数组中,传入参数数组即可。
function argsAsArray(fn, arr) {
return fn.apply(this, arr);
}
3.2 函数的上下文
- 将函数 fn 的执行上下文改为 obj 对象
- 示例:
- 方法1:
function speak(fn, obj) {
return fn.apply(obj);
}
- 方法2:
function speak(fn, obj) {
return fn.call(obj);
}
- 方法3:
function speak(fn, obj) {
return fn.bind(obj)();
}
3.3 返回函数
- 实现函数 functionFunction,调用之后满足如下条件:
1、返回值为一个函数 f
2、调用返回的函数 f,返回值为按照调用顺序的参数拼接,拼接字符为英文逗号加一个空格,即 ', ’
3、所有函数的参数数量为 1,且均为 String 类型
function functionFunction(str) {
return function(str2){
return str+", "+str2;
}
}
3.4 使用闭包
- 实现函数 makeClosures,调用之后满足如下条件:
1、返回一个函数数组 result,长度与 arr 相同
2、运行 result 中第 i 个函数,即 resulti,结果与 fn(arr[i]) 相同
function makeClosures(arr, fn) {
var result=[];
for(var i=0;i<arr.length;i++){
(function(i){
result[i] = function(){
return fn.call(null,arr[i]);
}
})(i);
}
return result;
}
3.5 二次封装函数
- 已知函数 fn 执行需要 3 个参数。请实现函数 partial,调用之后满足如下条件:
1、返回一个函数 result,该函数接受一个参数
2、执行 result(str3) ,返回的结果与 fn(str1, str2, str3) 一致 - 转载:牛客725600
function partial(fn, str1, str2) {
var result=function(str3){
return fn.bind(this,str1,str2)(str3);
};
return result;
}
bind不加后面的括号返回的是函数,加上后面的括号返回的是函数值,这也是bind和call和apply的主要区别,bind需要二次调用,而call和apply返回的是函数值,是直接调用。
3.6 使用 arguments
- 函数 useArguments 可以接收 1 个及以上的参数。请实现函数 useArguments,返回所有调用参数相加后的结果。本题的测试参数全部为 Number 类型,不需考虑参数转换。
function useArguments() {
var sums=0;
for(var i=0;i<arguments.length;i++){
sums+=arguments[i];
}
return sums;
}
3.7 使用apply调用函数
- 实现函数 callIt,调用之后满足如下条件
1、返回的结果为调用 fn 之后的结果
2、fn 的调用参数为 callIt 的第一个参数之后的全部参数 - 方法1,转载:我是一只小小小小菜鸟
function callIt(fn) {
var args=[];
for(var i=1;i<arguments.length;i++){
args.push(arguments[i]);
}
//上述代码等价为var args = Array.prototype.slice.call(arguments,1);
var result=fn.apply(null,args);
return result;
}
因为arguments并不是真正的数组。
3.8 二次封装函数
- 实现函数 partialUsingArguments,调用之后满足如下条件:
1、返回一个函数 result
2、调用 result 之后,返回的结果与调用函数 fn 的结果一致
3、fn 的调用参数为 partialUsingArguments 的第一个参数之后的全部参数以及 result 的调用参数 - 转载:希留
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;
}
3.9 柯里化?
- 已知 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 的调用参数
4.模块
- 完成函数 createModule,调用之后满足如下要求:
1、返回一个对象
2、对象的 greeting 属性值等于 str1, name 属性值等于 str2
3、对象存在一个 sayIt 方法,该方法返回的字符串为 greeting属性值 + ', ’ + name属性值
function createModule(str1, str2) {
var obj={
greeting:str1,
name:str2,
sayIt:function(){
return this.greeting +', ' +this.name;
}
};
return obj;
}
- 注意点:1)’, '为逗号+空格;2)sayIt方法中I大写(小写是i,不是L)
5.Number
5.1 二进制转换–十转二
- 获取数字 num 二进制形式第 bit 位的值。注意:
1、bit 从 1 开始
2、返回 0 或 1
3、举例:2 的二进制为 10,第 1 位为 0,第 2 位为 1
function valueAtBit(num, bit) {
var arr=[];
var i=0;
while(true){
arr.push(num%2);
num=Math.floor(num/2);
i++;
if(i==bit||num==0){
break;
}
//转换为2进制可以 var str = num.toString(2);
}
return arr[bit-1];
}
5.2 二进制转换–二转十
- 方法1:亲测可以,但是牛客网不行
function base10(str) {
var s=0;
str=str.split('');
str.reverse();
for(var i=0;i<str.length;i++){
s+=str[i]*(2**i);
}
return s;
}
//----------------------
//str='11000000';
//console.log(base10(str));
- 方法2:亲测可以,但是牛客网不行
function base10(str) {
var s=0;
for(var i=str.length-1;i>=0;i--){
s+=str[i]*(2**(str.length-1-i));
}
return s;
}
- 方法3:转载 刘放
function base10(str) {
/**
其它进制转十进制
parseInt(str,2)
parseInt(str,8)
parseInt(str,16)
*/
return parseInt(str,2);
}
5.3 二进制转换–十转二,补0至8位
- 方法1: 亲测可以,但是牛客网不行!
function convertToBinary(num) {
var arr=[];
var i=0;
while(true){
arr.push(num%2);
num=Math.floor(num/2);
i++;
if(num==0){
break;
}
}
while(arr.length<8){
arr.unshift(0);
}
return arr.join('');
}
- 方法2:转载:!(代码搬运工)
function convertToBinary(num) {
var str = num.toString(2);
while(str.length < 8) {
str = "0" + str;
}
return str;
}
5.4 乘法
- 求 a 和 b 相乘的值,a 和 b 可能是小数,需要注意结果的精度问题
- js中相乘出现小数则会出现bug,如0.0001*3,结果0.0003 0000 0000 0000 0003,因此需要保留几位小数
- 方法1:转载coypan
function multiply(a, b) {
return parseFloat((a*b).toFixed(10));//转化为浮点数并保留10位
}
6.对象
6.1 批量改变对象的属性
- 给定一个构造函数 constructor,请完成 alterObjects 方法,将 constructor 的所有实例的 greeting 属性指向给定的 greeting 变量。
function alterObjects(constructor, greeting) {
constructor.prototype.greeting=greeting;
}
6.2 属性遍历
- 找出对象 obj 不在原型链上的属性(注意这题测试例子的冒号后面也有一个空格~)
1、返回数组,格式为 key: value
2、结果数组不要求顺序 - 转载:希留
function iterate(obj) {
var arr = [];
//使用for-in遍历对象属性
for(var key in obj){
//判断key是否为对象本身的属性
if(obj.hasOwnProperty(key)){
//将属性和值按格式存入数组
arr.push(key+": "+obj[key]);
}
}
return arr;
}
- hasOwnproperty方法能返回一个布尔值,指出一个对象是否具有指定名称的属性**。此方法无法检查该对象的原型链中是否具有该属性,该属性必须为对象本身的属性。**
- 这里的key是自己定义的变量,而不是对象中的属性,通过变量访问属性时需要用方括号法,不能使用点表示法
7.小结
1.函数中传参常使用:apply、call和bind
2.进制转换:
var str = num.toString(2);//10进制转换为2进制,也可以转换为任意进制
var ins=parseInt(str,2);//2进制转为10进制,任意进制均可转换为10进制
3.通过变量访问属性时需要用方括号法,不能使用点表示法