js笔试题系列之三——函数

  在这一章以函数为主的讲解中,也会不可避免的牵涉到数组和对象的内容,这也不难理解,知识往后走牵涉的内容自然也越多。

(1)经典作用域问题

题一:

var a = 0
function f(){
  console.log(a); ==>undefined
  var a = 2;
  console.log(a); ==>2
}
f()

  第二次日志输出结果相对容易理解,关键是第一次打印结果并不是全局变量中的a,因为按照作用域链的查找规则,在函数执行的时候会先查找局部作用域,而此时局部作用域已经存在变量a,只不过还没有执行到赋值阶段,所以打印结果为undefined。

题二:

var a = 0
function f(a){
  console.log(a); ==>1
  var a = 2;
  console.log(a); ==>2
}
f(1)

  相比题一,这里多了个同名参数a,在函数体执行之前,a就已经被实参赋值,所以打印结果为1。

  关于作用域链:函数在执行的时候,会在内部生成执行上下文对象,它包含了两个属性,一个是活动对象,一个是scope属性;活动对象在函数体执行之初就被实参、函数体内变量、this对象、argument对象填充,scope属性指向上层函数的活动对象,当执行函数体内的变量查找时,会首先在本函数活动对象内查找,如果未找到,则根据scope指向的上层函数的活动对象内查找,以此类推,一直往上查找到全局window对象。

(2)预编译期与执行期

var f = function(){console.log(1)}
function f(){console.log(2)}
f() ==>1

  这里不能简单的以为js代码从上至下执行,所以下一个函数定义会覆盖上一个函数定义。实际上js在执行之前存在一个预编译期,所有通过var声明的变量和function声明的函数都在js的预编译期进行处理(包括对变量名进行索引和对function函数体进行解析),function函数体内部语句和相关的逻辑解析后,会存储在函数变量所指向的地址中等待函数调用。而在js的执行期,f又被重新赋值改变了引用地址,而实际上执行期间function f(){console.log(2)}这条声明式的语句并不会再去执行(在预编译期间已经处理)或产生任何其它改变,所以最终结果为1。

思考题:

function test() {
  alert("1");
  }
test();

function test() {
  alert("2");
}
test();

  

(3)函数判断数据类型并返回

function getType(obj){
  return Object.prototype.toString.call(obj).slice(8,-1);
}

  这种方法相比于使用typeof/instance/constructor等更加便捷,也是目前使用最多的方法。它利用了Object内置对象原型方法返回各类型特殊字符串的性质,可以全部区分出8种数据类型。但实际上Object.prototype.toString方法并不是专门为区分数据类型而设计的,它返回的字符串类型也并不是仅仅有8种,如果有必要需要考虑这两种特殊情况:arguments对象返回‘Arguments‘,dom对象返回‘HTMLDivElement‘。

(4)小试牛刀:函数实现取最大值,函数参数个数不限,比如fun(1,2)返回2,fun(1,2,3,4)返回4

方法一:

function max(){
  var arr = [].slice.call(arguments,0);
  arr.sort(function(a,b){
    return a-b;
  })
  return arr.pop();
}

  这里考察了arguments对象的使用和排序问题,需要注意的是这里需要将arguments对象先转换为真正的数组,才能使用sort方法,这里使用了[].slice.call,等效于Array.prototype.slice.call,它们地址引用是相同的。当然如果你换成下面这种解题答法我相信面试官会更开心的。

方法二:

function max(){
  return Math.max.apply(null,arguments);
}

  当然,这里并没有对参数类型进行考虑,如果要考虑一些异常情况或者,可以把这些特殊处理加上去。

(5)函数、数组、对象综合题

  已有数据对象为:

var students = [{
		name:‘lilei‘,
		sex:‘girl‘,
		scores:{
			Math:88,
			English:69
		}
	},
	......
]

  函数功能需求(1):

//功能需求:日志打印出存放男学生或女学生或全部学生的名字的数组
function getStudent(sex){
	//ToDo        ......
	console.log(arr);
}
getStudent();

  解答:

function getStudent(sex){
	var arr = []; //存放最终结果
	for(i in students){
		if(sex == undefined){
			arr.push(students[i].name);
		}else if(students[i].sex == sex){
			arr.push(students[i].name);
		}
	}
	console.log(arr);
}

  函数功能需求(2):

//功能需求:日志打印出存放某科目所有学生成绩的数组
function getScore(Subject){
	//ToDo
	...
	console.log(arr);
}
//打印所有学生数学成绩
//getScore(‘Math‘);

  解答:

function getScore(Subject){
	var arr = []; //存放该科目所有成绩
	for(i in students){
		arr.push(students[i].scores[Subject]);
	}
	console.log(arr);
}

  函数功能需求(3):

//功能需求:日志打印一个对象,该对象为某科目为最低分或最高分的学生名字、对于科目成绩
function getObj(Subject,maxOrMin){
	//ToDo
	...
  console.log(obj);
}
//打印数学最高分的学生名字和数学成绩:{name:***,Math:**}
getObj(‘English‘,‘min‘);

  解答:

function getObj(Subject,maxOrMin){
	var obj = {};
	var student;

	students.sort(function(a,b){
		return a.scores[Subject] - b.scores[Subject]; //按成绩从小到大排列
	})			

	if(maxOrMin == ‘max‘){
		student = students[students.length-1];
	}else{
		student = students[0];
	}

	obj.name = student.name;
	obj[Subject] = student.scores[Subject];
}

  

(6)函数中的this应用场景

题一:普通函数中的this

var a = 0;
function fun(){
  var a = ‘fun‘;
  console.log(this.a); ==>0
}

  普通函数中的this指向window对象

题二:方法中的this

var a = 0;
var obj = {
  a:‘obj‘,
  fun:function(a){
    console.log(this.a); ==>‘obj‘
  }
}
obj.fun(1);

  当函数作为对象的方法(对象的属性值为一个函数时,我们称此函数为该对象的方法)调用时,方法中的this指向调用方法的对象。

思考题:

var a = 0;
var obj = {
  a:‘obj‘,
  fun:function(a){
    return function(){
      console.log(this.a); ==> ? 自己动手试试,然后思考为什么
    }
  }
}
obj.fun(1)();

题三:在setTimeout和setInterval中的this

var a = 0;
var obj = {
  a:‘obj‘,
  fun:function(a){
    setTimeout(function(){
      console.log(this.a); ==>0
    },1000)
  }
}
obj.fun(1);

  在setTimeout和setInterval中this永远指向window,所以,假设在题三中期望输出结果为obj对象的a属性值,则可以这样修改:

var a = 0;
var obj = {
  a:‘obj‘,
  fun:function(){
    var _this = this;
    setTimeout(function(){
      console.log(_this.a); ==>‘obj‘
    },1000)
  }
}
obj.fun();

题四:作为构造函数调用

var a = 0;
function Obj() {
    this.a = 1;
}
var o = new Obj();
console.log(o.a); ==>1

  这是个简单的构造函数,在new操作过程中,实例化对象将在构造函数中替代this指向,相当于Obj.call(o)。

题五:在dom元素的事件句柄中

<div onclick="fun(this)">ddd</div>
<script>
function fun(el) {
    console.log(el); ==>触发事件句柄的dom对象
}
</script>

(7)面向对象问题

题一:实现一个继承

  

时间: 2024-10-13 18:22:47

js笔试题系列之三——函数的相关文章

js笔试题系列之二——数组

(1)快速创建一个数组,数组中含有100个值为0元素. 方法一: var arr = new Array(100); for(var i=0;i<100;i++){ arr[i] = 0; } 方法二: var arr = new Array(100); arr.join('0').split(''); //注意此方法结果0为字符类型 面试官会喜欢哪个答案呢? (2)经典的数组去重问题 数组去重可以说是各大公司前端笔试中的常见题,以下列出几种典型的解决方法 方法一:传统双循环对比法 functi

js笔试题系列之——基础类型与运算符

前端技术的发展速度大家有目共睹,js的ECMA标准也不再是3的天下,但不管再怎么山雨欲来风满楼,基础语法还是得温故而知新.无论你是初学则还是多年js的编程者,都可以试着做做下面的测试题,我相信总还是会有些收获的.因为全部是自己总结和手打的,有纰漏错误之处请留言,谢谢. 一:考察基本数据类型与运算符 (1) var a; console.log(typeof a); ==>undefined 先以一个最常见也是最简单的测试案例开始,未定义的变量或者未赋值则为undefined (2) var a

容易答错的JS笔试题

1,考察this var length = 10 function fn(){     alert(this.length) } var obj = {     length: 5,     method: function(fn) {         fn() // ?         arguments[0]() // ?     } } obj.method(fn) 这里的坑主要是arguments,我们知道取对象属于除了点操作符还可以用中括号,这里fn的scope是arguments,即

JS笔试题

1,考察this var length = 10function fn(){ alert(this.length)}var obj = { length: 5, method: function(fn) { fn() // ? arguments[0]() // ? }}obj.method(fn)这里的坑主要是arguments,我们知道取对象属于除了点操作符还可以用中括号,这里fn的scope是arguments,即fn内的this===arguments,调用时仅传了一个参数fn,因此le

笔试题系列001

测试笔试题类型:软件测试| 试题:55道试题(50道选择题,5道问答题)http://bbs.sjtu.edu.cn/bbsanc,path,%2Fgroups%2FGROUP_9%2FJobInfo%2FD7CD26755%2FD85486036%2FM.1131274669.A.html http://202.197.191.206:8080/38/text/test/test_2/shijuan2.htm 软件工程 http://test.examw.com/410/P6517/一.单选题

这道JS笔试题你做对了吗?

昨天在看一道笔试题的时候本以为很简单,但是结果不是我想象的那样,直接上笔试题. const array = new Array(5).map((item) => { return item = { name: '1' } }); console.log(array); // 请写出输出结果 我想象的答案:[{name: '1'}, {name: '1'}, {name: '1'}, {name: '1'}, {name: '1'}]; 实际的答案:[empty × 5] 为什么会这样了? 猜想1

由几道JS笔试题引发的知识点探究一——JS有哪些全局函数?

首先要明确什么是JS.各位读者肯定都是在学习和研究JS的,或是菜鸟或是大牛,但是你考虑过什么是JS吗?乍一看来我这问题有点死抠字眼的味道,但在学习一门语言的时候就必须有这种打破沙锅问到底的精神.只有这样才能学得深入,才能学到这门语言的本质.几句絮叨之后,我们回到之前的问题——什么是JS?我们挂在嘴边的JS实际上有两种含义——一,ECMAScript,也就是所谓的JS标准:二,宿主环境中的JS,因为JS基本上是用于web开发的(JS官方称JS为"language of the web")

蛮考验基础的JS笔试题(有坑小心!)

1.  考察this 1 var length = 10 2 function fn(){ 3 alert(this.length) 4 } 5 var obj = { 6 length: 5, 7 method: function(fn) { 8 fn() // ? 9 arguments[0]() // ? 10 } 11 } 12 obj.method(fn) 这里的坑主要是arguments,我们知道取对象属于除了点操作符还可以用中括号,这里fn的scope是arguments,即fn内

由几道JS笔试题引发的知识点探究二——强制类型转换

强制类型转换的概念相信大家一定不陌生,例如整数和浮点数进行算术运算,整数会在后台转型为浮点数.JS作为一门弱类型的动态脚本语言,任何两种数据类型之间都可以进行性转换而不会报错,这就带来了一整套错综复杂的类型转换规则.例如我们的题目 alert('5'+5),大家都知道答案是'55',但为什么这里不将string转换成number而要将number转换成string呢?在其他情况下也都要将string转型成number吗?下面我们就来做一次完整的总结. 一.何时转型为boolean? 1. 逻辑非