2. JavaScript数据类型及语言基础(一)
2.1 任务描述
- 创建一个JavaScript文件,比如
util.js
; - 实践判断各种数据类型的方法,并在
util.js
中实现以下方法:// 判断arr是否为一个数组,返回一个bool值 function isArray(arr) { // your implement } // 判断fn是否为一个函数,返回一个bool值 function isFunction(fn) { // your implement }
解题思路:
1.说道判断类型,第一个想到的就是typeof进行判断,但是typeof的作用实在有限!判断的结果只有六个:string,number,boolean,function,undfined,object;
而且中间存在bug,console.log(typeof null) = object;而且对于Array,返回的全是obejct。typeof存在很大的局限性!
2. 第二种方法,利用instanceof。如var a = []; console.log(a instanceof Array) //ture ;console.log(a instanceof Object) //ture;因为Array是Object的一个子类,所以instanceof也有很大的局限性!
3.最后介绍一种官方认可的方法,而且比较有效的方法,Object.prototype.toSting.call(arr) == "[object Array]";这个方法可以判断所有的类型!
代码如下:
// 判断arr是否为一个数组,返回一个bool值 function isArray(arr) { // your implement return Object.prototype.toString.call(arr) === "[object Array]"; } // 判断fn是否为一个函数,返回一个bool值 function isFunction(fn) { // your implement return Object.prototype.toString.call(fn) === "[object function]"; }
- 了解值类型和引用类型的区别,了解各种对象的读取、遍历方式,并在
util.js
中实现以下方法:
// 使用递归来实现一个深度克隆,可以复制一个目标对象,返回一个完整拷贝// 被复制的对象类型会被限制为数字、字符串、布尔、日期、数组、Object对象。不会包含函数、正则对象等function cloneObject(src) { // your implement } // 测试用例:var srcObj = { a: 1, b: { b1: ["hello", "hi"], b2: "JavaScript" } }; var abObj = srcObj; var tarObj = cloneObject(srcObj); srcObj.a = 2; srcObj.b.b1[0] = "Hello"; console.log(abObj.a); console.log(abObj.b.b1[0]); console.log(tarObj.a); // 1console.log(tarObj.b.b1[0]); // "hello"
解题思路:
1.首先要知道,js中数据分为原始类型和引用类型,对于原始类型,可直接进行复制!对于引用类型,引用的是指向原始对象的指针,所以原始对象进行改变的时候,引用类型也会跟着改变!《JavaScript高级程序设计》是这样解释的:当从一个变量向另一个变量复制引用类型的值时,同样也会讲存储在变量对象中的值复制一份放到为新变量分配的空间中。不同的是,这个值的副本实际上是一个指针,而这个指针指向存储在堆中的一个对象。复制操作结束后,两个变量实际上将引用同一个对象。因此,改变其中一个变量,就会影响另一个变量!
2.引用类型中的date也能够直接引用,所以,首先判断是不是引用类型,如果不是,则直接复制!如果是引用类型,在进行判断,如果是date,则直接复制,如果不是数组,在进行判断,判断是为object还是array;
3.在复制的时候,还要考虑是继承的属性还是自身的属性!
ps:函数对象苏然是引用类型,但是函数的克隆通过浅克隆就行!
代码如下:
// 使用递归来实现一个深度克隆,可以复制一个目标对象,返回一个完整拷贝 // 被复制的对象类型会被限制为数字、字符串、布尔、日期、数组、Object对象。不会包含函数、正则对象等 function cloneObject(src) { // your implement var result;//定义克隆后的结果 if (typeof(src) == "object" ) {//判断是否是引用类型 if (Object.prototype.toString.call(src) === "[object Data]") {//如果是data类型,直接克隆 result = src; } else { resule = (Object.prototype.toString.call(src) === "[object Array]")?[]:{};//先判断对象的类型 if (src.hasOwnProperty(i)) {//判断是否为对象自身的属性 if (typeof src[i] == "object") {//如果为对象,遍历复制 result[i] = cloneObject(src[i]); } else {//如果为数组,一对一克隆! result[i] = src[i]; } } } } else {//当为原始类型时,直接复制! result = src; } }
- 学习数组、字符串、数字等相关方法,在
util.js
中实现以下函数
// 对数组进行去重操作,只考虑数组中元素为数字或字符串,返回一个去重后的数组function uniqArray(arr) { // your implement } // 使用示例var a = [1, 3, 5, 7, 5, 3]; var b = uniqArray(a); console.log(b); // [1, 3, 5, 7] //去除开头和结尾的空白 function trim(arr) { // your implement } // 使用示例var str = ' hi! '; str = trim(str); console.log(str); // 'hi!' // 实现一个遍历数组的方法,针对数组中每一个元素执行fn函数,并将数组索引和元素作为参数传递function each(arr, fn) { // your implement } // 其中fn函数可以接受两个参数:item和index // 使用示例var arr = ['java', 'c', 'php', 'html']; function output(item) { console.log(item) } each(arr, output); // java, c, php, html // 使用示例var arr = ['java', 'c', 'php', 'html']; function output(item, index) { console.log(index + ': ' + item) } each(arr, output); // 0:java, 1:c, 2:php, 3:html // 获取一个对象里面第一层元素的数量,返回一个整数function getObjectLength(obj) {} // 使用示例var obj = { a: 1, b: 2, c: { c1: 3, c2: 4 } }; console.log(getObjectLength(obj)); // 3
解题思路:
1.去重,直接遍历数组,利用数组的indexOf方法,判断新的数组是否存在数组中的每一个位置的值,如果不存在则添加进数组,反正抛弃。
2.去除开头和结尾的空白,直接利用正则表达式,然后replace将匹配到的开头和结尾的空白字符给替换!
3.对于每个元素都执行一次,见代码!
4.首先定义一个count,用来存放keys出现的次数,因为keys的值都在对象的第一层!
代码如下:
// 对数组进行去重操作,只考虑数组中元素为数字或字符串,返回一个去重后的数组 function uniqArray(arr) { // your implement var result = [];//定义一个新的数组,用于存放没有重复的元素 for (var i = 0; i < arr.length; i++) { if(result.indexOf(arr[i]) = -1) { result.push(arr[i]); } } return result; } // 很多同学肯定对于上面的代码看不下去,接下来,我们真正实现一个trim // 对字符串头尾进行空格字符的去除、包括全角半角空格、Tab等,返回一个字符串 // 尝试使用一行简洁的正则表达式完成该题目 function trim(str) { // your implement var result = ""; result = str.replace(/^s+|s+$/g,""); return result; } // 实现一个遍历数组的方法,针对数组中每一个元素执行fn函数,并将数组索引和元素作为参数传递 function each(arr, fn) { // your implement if(!isArray(arr)){ return false; } if(!isFunction(fn)){ return false; } for (var i = 0; i < arr.length; i++) { fn(arr[i],i); } } // 获取一个对象里面第一层元素的数量,返回一个整数 function getObjectLength(obj) { var count = 0; for (var keys in obj) { count++; } return count; }
- 学习正则表达式,在
util.js
完成以下代码
// 判断是否为邮箱地址 function isEmail(emailStr) { // your implement } // 判断是否为手机号 function isMobilePhone(phone) { // your implement }
参考资料:
正则表达式30分钟入门教程http://deerchao.net/tutorials/regex/regex.htm
代码如下:
//判断是否是邮箱地址 function isEmail(str){ var reg = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/; return reg.test(str); } // 判断是否为手机号 function isMobilePhone(phone) { // your implement var reg = /^1[3-8]d{9}/ return reg.text(phone); }