避免全局变量
给定的 js 代码中存在全局变量,请修复
/*题目给出代码*/
function globals() {
myObject = {
name : 'Jory'
};
return myObject;
}
/*
一开始我没看懂问题——>给定的 js 代码中存在全局变量,请修复。
后来看了讨论才知道 myObject 是全局变量,没反应过来。。然后直接修改代码就可以。
在Javascript语言中,声明变量使用的都是关键字var
如果不使用var而直接声明变量,则该变量为全局变量。
*/
function globals() {
var myObject = {//加个var 声明就可以了
name : 'Jory'
};
return myObject;
}
正确的函数定义
请修复给定的 js 代码中,函数定义存在的问题
/*原代码如下*/
function functions(flag) {
if (flag) {
function getValue() { return 'a'; }
} else {
function getValue() { return 'b'; }
}
return getValue();
}
/*
咋一看没啥问题啊。仔细看看发现问题了 代码整理一下如下:
*/
function functions(flag) {
var getValue;
getValue = function () {
return 'a';
};
getValue = function () {//合着是给getValue 重写函数了, if else
return 'b';
};
if (flag) {}
else {}
return getValue();
}
/*
else中的语句相当于将if中的function重写,因此无论flag为何值,
返回的方法始终为重写后的方法。将方法赋值给一个变量,
方法就不会被重写,因此才能得到正确的结果。
为啥呢?
查了一下,函数声明提前,后面的会覆盖前面的,而函数表达式则在执行到if-else语句时才会被调用,故不会被重写。
*/
正确的使用 parseInt
修改 js 代码中 parseInt 的调用方式,使之通过全部测试用例
输入例子:
parse2Int('12'); parse2Int('12px'); parse2Int('0x12')
输出例子:
12; 12; 0
/*原代码*/
function parse2Int(num) {
return parseInt(num);
}
/*修改结果*/
function parse2Int(num)
{
return parseInt(num,10);
}
/*
举例,如果 string 以 "0x" 开头,parseInt() 会把 string 的其余部分解析为十六进制的整数。
如果 string 以 0 开头,那么 ECMAScript v3 允许 parseInt()
的一个实现把其后的字符解析为八进制或十六进制的数字。如果 string 以 1 ~ 9 的数字开头
parseInt() 将把它解析为十进制的整数。.
呃..这是别人解释的,因为我很少用到 进制解析的问题,就没深入查,有兴趣的可以深入查看一下
*/
完全等同
判断 val1 和 val2 是否完全等同
/*原代码*/
function identity(val1, val2) {
}
/*结果*/
function identity(val1, val2) {
return val1===val2;
}
/*
== equality 等同,=== identity 恒等。 没啥说的
*/
计时器
实现一个打点计时器,要求
1、从 start 到 end(包含 start 和 end),每隔 100 毫秒 console.log 一个数字,每次数字增幅为 1
2、返回的对象中需要包含一个 cancel 方法,用于停止定时操作
3、第一个数需要立即输出
/*直接贴结果了*/
function count(start, end) {
console.log(start++);//调用立刻打印。注意是后加加 返回的是旧值 也就是 打印的是1 实际上start已经是2了
var t=setInterval(function(){//定时器 一直执行
/*if(start<=end) 这里说一下,一开始我在想怎么获取start到end之间的数字呢?后来反应过来了,智商是硬伤啊!!*/
if(start<=end){ console.log(start++)//后加加 打印出来的是2 实际上start 已经是3了}
/*最后一次运行完start 是10 再进入if判断 start 是11 进入else停止定时器*/
else{clearInterval(t)}
},100);
return{
cancel:function(){//返回一个匿名的对象。
clearInterval(t);
}
}
}
count(1,10);
//count.cancel();停止计数器
函数传参
将数组 arr 中的元素作为调用函数 fn 的参数
输入例子:
argsAsArray(function (greeting, name, punctuation) {return greeting + ', ' + name + (punctuation || '!');}, ['Hello', 'Ellie', '!'])
输出例子:
Hello, Ellie!
function argsAsArray(fn, arr) {
return fn(arr[0],arr[1],arr[2]);
}
/*上面是我自己想到的笨方法,符合提议,但是倍儿傻....反正很傻。*/
/*以下是高手写的*/
function argsAsArray(fn, arr) {
return fn.apply(this, arr);
}
/*
调用函数可以使用call或者apply这两个方法
区别在于call需要将传递给函数的参数明确写出来
是多少参数就需要写多少参数
而apply则将传递给函数的参数放入一个数组中
传入参数数组即可
Function.apply(obj,args)方法能接收两个参数
obj:这个对象将代替Function类里this对象
args:这个是数组,它将作为参数传给Function(args-->arguments)
call:和apply的意思一样,只不过是参数列表不一样.
Function.call(obj,[param1[,param2[,…[,paramN]]]])
obj:这个对象将代替Function类里this对象
params:这个是一个参数列表
.apply示例:
<script type="text/javascript">
/*定义一个人类*/
function Person(name,age) {
this.name=name; this.age=age;
}
/*定义一个学生类*/
functionStudent(name,age,grade) {
Person.apply(this,arguments); this.grade=grade;
}
//创建一个学生类
var student=new Student("qian",21,"一年级");
//测试
alert("name:"+student.name+"\n"+"age:"+student.age+"\n"+"grade:"+student.grade);
//大家可以看到测试结果name:qian age:21 grade:一年级
//学生类里面我没有给name和age属性赋值啊,为什么又存在这两个属性的值呢,这个就是apply的神奇之处.
</script>
分析: Person.apply(this,arguments);
this:在创建对象在这个时候代表的是student
arguments:是一个数组,也就是[“qian”,”21”,”一年级”];
也就是通俗一点讲就是:用student去执行Person这个类里面的内容,在Person这个类里面存在this.name等之类的语句,这样就将属性创建到了student对象里面
*/
函数的上下文
将函数 fn 的执行上下文改为 obj 对象
输入例子:
speak(function () {return this.greeting + ', ' + this.name + '!!!';}, {greeting: 'Hello', name: 'Rebecca'})
输出例子:
Hello, Rebecca!!!
function speak(fn, obj) {
return fn.apply(obj, obj);
}
/*
在JavaScript中,函数是一种对象,其上下文是可以变化的,
对应的,函数内的this也是可以变化的,函数可以作为一个对象的方法,
也可以同时作为另一个对象的方法,可以通过Function对象中的call
或者apply方法来修改函数的上下文
,函数中的this指针将被替换为call或者apply的第一个参数。
将函数 fn 的执行上下文改为 obj 对象,
只需要将obj作为call或者apply的第一个参数传入即可。
*/
返回函数
实现函数 functionFunction,调用之后满足如下条件:
1、返回值为一个函数 f
2、调用返回的函数 f,返回值为按照调用顺序的参数拼接,拼接字符为英文逗号加一个空格,即 ', '
3、所有函数的参数数量为 1,且均为 String 类型
输入例子:
functionFunction('Hello')('world')
输出例子:
Hello, world
function functionFunction(str) {
var f = function(s){
return str+", "+s;
}
return f;
}
/*
首先执行functionFunction('Hello'),传入参数str,然后返回函数f,
f与('world')组合,执行f('world'),传入参数s,f返回str+",
"+s,即Hello, world。注意中间的逗号后面有一个空格。
*/
使用闭包
实现函数 makeClosures,调用之后满足如下条件:
1、返回一个函数数组 result,长度与 arr 相同
2、运行 result 中第 i 个函数,即 result[i](),结果与 fn(arr[i]) 相同
输入例子:
var arr = [1, 2, 3]; var square = function (x) { return x * x; }; var funcs = makeClosures(arr, square); funcs[1]();
输出例子:
4
说实话,我没看懂题,我是看了答案之后又回来的读的题,之后还是没看懂。。。。智商啊,又他妈的下线了。。。不过我知道是个闭包的应用,所以我贴一个自己在工作中的用到的tab()函数,也应用了闭包。
/*答案代码*/
function makeClosures(arr, fn) {
var fun=function(i){//定义一个函数fun
return function(){ //函数返回给result的是一个匿名函数。
return fn(arr[i]); //这个匿名函数的返回值是fn(arr[i])
}
}
var result=[]; //声明要返回的一个数组
for(var i=0;i<arr.length;i++){//数组result的长度和arr的长度相同
result[i]=fun(i);//数组的值等于函数的返回值。
}
return result;
}
/*我的tab切换方法 里面也用到了闭包*/
function tab() {
var tabs = document.querySelector(".ll-tab").getElementsByTagName("div");//标签
var pages = document.querySelector("#all-ll-list").getElementsByTagName("section");//需要显示的页面
var show = function (i) {
return function () {//闭包,返回一个函数给show.
var it = i;
if (tabs[i].className != "select") {
tabs[i].className = "select";
pages[i].className = "show";
for (var j = 0, leng = tabs.length; j < leng; j++) {
if (tabs[j].className == "select" && tabs[j] != tabs[it]) {
tabs[j].className = "";
}if (pages[j].className == "show" && pages[j] != pages[it]) {
pages[j].className = "";
}
}
}
}
};
for (var i = 0, len = tabs.length; i < len; i++) {
tabs[i].onclick = show(i);//循环绑定show方法。
}
}
tab();
使用 arguments
函数 useArguments 可以接收 1 个及以上的参数。请实现函数 useArguments,
返回所有调用参数相加后的结果。本题的测试参数全部为 Number 类型,不需考虑参数转换。
输入例子:
useArguments(1, 2, 3, 4)
输出例子:
10
总算是有一道能看懂的题了.....
这个题简单就是应用arguments,贴下arguments部分的感念
1、在JavaScript中,arguments对象是比较特别的一个对象,实际上是当前函数的一个内置属性。arguments非常类似Array,但实际上又不是一个Array实例。
2、arguments对象的长度是由实参个数而不是形参个数决定的。形参是函数内部重新开辟内存空间存储的变量,但是其与arguments对象内存空间并不重叠。对于arguments和值都存在的情况下,两者值是同步的,但是针对其中一个无值的情况下,对于此无值的情形值不会得以同步。
function useArguments() {
var t=0;
for(var i=0;i<arguments.length;i++){
t+=arguments[i];
}
return t;
}
/*完美!棒棒的!初步书写的代码*/
/*以下是炫技时间*/
function useArguments() {
var arr=Array.prototype.slice.call(arguments);
return eval(arr.join("+"));
/*eval(arr.join("+"))在数组求和的时候用过,写这代码的时候就已经忘了....又翻代码才想起来的*/
}
使用 apply 调用函数
实现函数 callIt,调用之后满足如下条件
1、返回的结果为调用 fn 之后的结果
2、fn 的调用参数为 callIt 的第一个参数之后的全部参数
输入例子:
var a = 1; var b = 2; var test = function (first, second) { return first === a && second === b;}; callIt(test, a, b);
输出例子:
true
function callIt(fn) {
/*因为arguments并非真正的数组,因此要获得callIt的第一个参数之后的所有参数,
不能直接使用slice方法截取,需要先将arguments转换为真正的数组才行。*/
var args = Array.prototype.slice.call(arguments,1);//从第二个位置开始截取所有参赛,返回新数组
return fn.apply(null,args)//第一个参赛为空的话,默认为this;给apply传递null,“”空字符串,默认都是this
}
/*
arguments能获得函数对象传入的参数组,类似与一个数组,能够通过length获取参数个数,能通过下标获取该位置的参数,但是它不能使用forEach等方法。
*/