函数面试题解析

1、写一个js函数,实现对一个数字每3位加一个逗号,如输入100000, 输出100,000(不考虑负数,小数)

var arr-[];
function main(num) {     
 if (num=== null) return;      
 var n = parseInt(num).tostring();
 s(n);
 Function s(num){      
 if(num. length>3)      
 arr[ arr. length]=num.slice(-3);s(num.slice(0,-3));      
 else{      
 arr[ arr. length]=num;
 }main( 123456789);  

本题是js实现number.toLocaleString()方法,面试题做了简化不考虑负数小数,此题主要是考数据类型及字符串操作,答案不唯一。
按现实思路解题,现实中添加千位分隔符是从后到前,每3位添加逗号,所以这里输入数据转换成字符串后,利用slice方法的输入负数参数从后取的特点,从后取三位数字保存在数组中,并把取剩后的数据递归重复取值,直到数据不足3位,把剩下一起存入数组中。这时数组中按顺序保存从后到前的分割数据。实例中数组是[‘789’,’456’,’123’]。通过reverse方法倒叙输出,并通过join方法添加逗号。

2、给定一个字符串,找出其中无重复字符的最长子字符串长度

var lengthOfLongestSubstring = function(s){
			var str = '';//存放当前最大无重复项字符串
			var len = 0;//存放当前当前最大无重复项字符串长度
			for(var i=0;i<s.length;i++){
				var char = s.charAt(i);
				var index = str.indexOf(char);
				if(index === -1){  //遍历s将元素挨个放入到str中,每放入一次判断str中是否有重复项
					str += char;
					len = len<str.length?str.length:len;//记录最大长度项,每次重新记录str进行判断,是否大于上次一次最大项
				}
				else{
					str = str.substr(index + 1) + char; //从当前重复项开始重新记录str
				}
			}
			return len;
		}

3、下列代码执行完之后x,y,z的结果分别是什么

var x = 1, y = z = 0; 

function add(n) { 

n = n+1; 

  } 

y = add(x); //2

function add(n) { 

n = n + 3; 

} 

z = add(x); //
// x        1

// y 		undefined

// z 		undefined

因为函数没有return,所以为undefined

4、下列代码执行完后x,y,z的结果为什么

var x = 1, y = z = 0; 

function add(n) { 

return n = n+1; 

  } 

y = add(x); 

function add(n) { 

return n = n + 3; 

} 

z = add(x); 

console.log(x,y,z)

//问执行完毕后 x, y, z 的值分别是多少? 

//错误:

//x 1

//y 	 2

//z 4

//正确:

//x 1

//y 	 4

//z 4

因为当函数声明重名时后面的会覆盖前面的

5、下列代码的运行结果为

            console.log(typeof [1, 2]);
            console.log(typeof 'leipeng');
            var i = true; 
            console.log(typeof i); 
            console.log(typeof 1); 
            var a; 
            console.log(typeof a);
            function a(){};
            console.log(typeof a);
            console.log(typeof 'true'); 

运行结果为依次打印object string boolean number function function string。

引擎会在解释JavaScript代码之前对齐进行编译。编译阶段的一部分工作就是找到所有的声明,并用合适的作用域将它们关联起来。而声明会从它在代码中出现的位置被“移动”到各自作用域的顶端,这个过程叫做提升。相较之下,当引擎执行LHS查询时,如果在顶层(全局作用域)中也无法找到目标变量,全局作用域中就会创建一个具有该名称的变量,并将其返还给引擎,前提是程序运行在非“严格模式”下。另外值得注意的是,每个作用域都会进行提升操作,而且函数声明会被提升,但是函数表达式却不会被提升。函数声明和变量声明都会被提升。但是一个值得注意的细节(这个细节可以出现在有多个“重复”声明的代码中)是函数会首先被提升,然后才是变量。

所以,function a(){}会被先提升到作用域顶端,当编译到 var i =true;时,JavaScript会将其看成两个声明:var i;和i=true;。第一个定义声明是在编译阶段进行的,并把声明提前到作用域(此程序中为全局作用域)的顶端第二个声明会被留在原地等待执行阶段。同理编译到var a时,把声明提升,但它是重复的声明,因此被忽略了。

6、k的运行结果

            for(i=0, j=0; i<4, j<6; i++, j++){
                k = i + j;
            }
            console.log(k);
            

在这里插入图片描述
语句1: 1.初始化变量; 2.是可选的,也可以不填;3.可以写任意多个,与语句3中变量名对应
语句2: 1.执行条件 2. 是可选的(若不填,循环中必须要有break,不然死循环)3. 如果出现多个一逗号为间隔的判断依据,则以分号前的最后一项为准。
语句3: 1. 改变初始变量的值 2.是可选的
所以这个for循环的真正的执行条件是j<6 ,每执行一次循环i和j就加一,共执行6次循环,即最后i=j=5;k=10,打印10。
7、

var fn = function() {
       console.log('hello world');
}
fn(); // hello world
function fn() {
       console.log('hello');
}
hello(); // hello world

顺序执行代码:如下:

var fn;
function fn() {
console.log(‘hello’);
}
fn= function(){
console.log(‘hello world’);
}
fn(); // hello world
fn();// hello world

8、

            var name = 'laruence';     
            function echo()
            {         
                console.log(name);   
            }      
            function env()
            {
                var name = 'eve';         
                echo();   
            }      
            env();

打印 laruence
作用域负责收集并维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限。作用域共有两种主要的工作模型。第一种是最为普遍的,被大多数编程语言所采用的词法作用域。另外一种叫作动态作用域,仍有一些编程语言在使用(比如Bash脚本、Perl中的一些模式等)
需要说明的是JavaScript中的作用域是词法作用域。当一个块或函数嵌套在另一个块或函数中时,就发生了作用域的嵌套。因此,在当前作用域中无法找到某个变量时,引擎就会在外层嵌套的作用域中继续查找,直到找到该变量,或抵达最外层的作用域(也就是全局作用域)为止。
词法作用域是一套关于引擎如何寻找变量以及会在何处找到变量的规则。词法作用域最重要的特征是它的定义过程发生在代码的书写阶段(假设没有使用eval()或with)。而动态作用域并不关心函数和作用域是如何声明以及在何处声明的,只关心它们从何处调用。换句话说,作用域链是基于调用栈的,而不是代码中的作用域嵌套。
9、

            var x=8;
            var objA = {
                x:'good',
                y:32
            }

            function add(x,y){
                console.log(x.y+y);
            }

            function fn(x,y){
                x.y=5;
                y(x,3);
            }
            fn(objA,add);
            console.log(objA);

结果是依次打印8 {x:“good”,y:5};

首先编译器对代码进行编译,先提升两个函数表达式,然后提升声明x,objA,所以代码片段会被引擎理解为如下形式:

            function add(x,y){
                console.log(x.y+y);
            }
            function fn(x,y){
                x.y=5;
                y(x,3);
            }
            var x;
            var objA;
            x=8;
            objA={
            x:‘good’,
            y:32
            }
            fn(objA,add);
            console.log(objA);

然后引擎运行代码fn(objA,add),objA和add是实参被传入函数fn中,所以相当于运行函数fn(objA,add)。在函数内部出现x.y=5。首先对象取属性操作的优先级最高,其次访问对象属性有两种方法,一种是本题中使用的点表示法,这也是很多面向对象语言中通用的语法。不过,在JavaScript也可以使用方括号表示法来访问对象的属性。在使用方括号语法时,应该将要访问的属性以字符串的形式放在方括号中,从功能上看,这两种访问对象属性的方法没有任何区别。但方括号语法的主要优点是可以通过变量来访问属性。而点表示法 不能使用变量来访问属性,所以本题中的x.y=5等同于objA.y=5,即在全局作用域中找到objA并把其y属性改变为5。而y(x,3)就等同于add(objA,3),即运行函数add,并为形参x,y传入实参objA和3,而且同上面所讲对象取属性优先级更高,所以函数add内部可以看为console.log(objA.y+3),对objA进行RHS查询,并得到它的y属性值为5,所以打印值为5。
10、

            var num=5;
            function func1(){
                 var num=3;
                 var age =4;
                 function func2(){
                     console.log(num);
                     var num ='ivan';
                     function func3(){
                       age =6;  
                     }
                     func3();
                     console.log(num);
                     console.log(age);
                }
                func2();
            }
            func1();

结果为依次打印 undefined ivan 6
首先引擎在解释JacaScript代码之前首先对其编译,编译阶段中的一部分工作就是找到所有的声明,并用合适的作用域将它们关联起来。引擎会在全局作用域顶端声明函数func1,然后声明全局变量num。在函数func1的作用域顶端先声明函数func2。在函数func2内部作用域的顶端声明函数func3,然后声明变量num。引擎所理解的代码格式如下

            function func1(){
                function func2(){
                    function func3(){
                        age =6;  
                    }
                    var num;

                    console.log(num);//undefined
                    num ='ivan';
                    func3();
                    console.log(num);//ivan
                    console.log(age);//6
                }
                var num;
                var age;

                num =3;
                age =4;
                func2();
            }
            var num;

            num=5;
            func1();

然后引擎开始从上到下执行代码,首先执行num=5,对num进行LHS查询,在全局作用域中找到变量num并将值赋给它。
然后运行函数func1,依次对变量num,age进行LHS查询,查询规则为从里到外,即从自己的作用域依次查询嵌套它的外部作用域。所以这两个变量直接在自己作用域内找到已经被声明的变量空间,然后把值3 ,4依次赋值给它们。
然后运行函数func2,首先运行console.log(num);对num进行RHS查询,在func2作用域中找到被声明的变量num,但是该变量并未赋值,所以打印结果为undefined。然后运行num=’ivan’;对num进行LHS查询,在func2作用域中找到num并赋值为ivan。
然后运行函数func3,运行age=6;对age进行LHS查询,在func3作用域内没有找到该变量,然后到包裹该作用域的func2作用域中查找该变量,找到该变量,并对其重新赋值为6。
函数func3内部代码运行完后,再接着运行func2内部代码console.log(num),对num进行RHS引用,在其所在作用域内找到被赋值为ivan的变量num,然后把得到的值传给console.log(),即打印出ivan。
接着执行代码console.log(age);和上步同理,对age进行RHS查询,在其所在作用域内没有找到变量age,然后向上级作用域接着查找,找到已被重新赋值为6的变量age,并把值传递给console.log(),所以打印结果为6。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值