JavaScript数据类型及语言基础

1. 判断arr是不是一个数组,返回一个bool值。

首先javascript有5大基本数据类型:Undefined,Null,Boolean,Number和String(双无BNS)

还有一个引用数据类型:Object,它包括以下三大类:

  1. Native Object(原生对象): ECMAScript本身自带的对象,是在脚本运行环境中程序员创建来使用的,包括:Object(基础类型)、Array、Date、Function、RegExp;另外还包括三个基本包装类型:Boolean、Number、String,有了它们三个我们可以将基本类型值当作对象来访问(使用他们的属性和方法)。
  2. Build-in Object(内置对象): JavaScript语言提供的不依赖于执行宿主的内建对象,如:Global、Math;内建对象都是Native Object。
  3. Host Object(宿主对象):JavaScript语言提供的任何依赖于宿主环境的对象,所有非Native Object的对象都是宿主对象,如:IE中的window,WScript中的wscript实例,以及任何用户创建的类。

所以我们判断的数组(Array)就是复杂数据类型Object中的其中一类,我们需要使用Object自带的方法来判断它——

Object.prototype.toString:取得对象的一个内部属性[[Class]],然后依据这个属性,返回一个类似于"[object Array]"的字符串作为结果。

function isArray (arr) {
return Object.prototype.toString.call(arr) === '[object Array]';
}

不直接调用arr.toString,而用call的原因:虽然Array继承自Object,也会有toString方法,但是这个方法有可能会被改写(数组重写了该方法:arr.toString的效果相当于join()方法连接),Object.prototype能一定程度保证其“纯洁性”。

2. 判断fn是否为一个函数,返回一个bool值。

我个人认为使用typeof操作符即可,如果严密一点的话可以使用上述判断数组的方法。

function isFunction (fn) {
return (typeof fn === 'function');
}
// or
function isFunction (fn) {
return Object.prototype.toString.call(arr) === '[Object Function]';
}

3. 使用递归来实现一个深度克隆,可以复制一个目标对象,返回一个完整拷贝,被复制的对象类型会被限制为数字、字符串、布尔、日期、数组、Object对象。不会包含函数、正则对象等。

基本是考虑克隆对象时的三种情况——重新构造和遍历

function cloneObject (src) {
// 对于基本数据类型,只要直接返回即可
if (src == null || typeof src != 'object') {
return src;
} // 对于对象分为以下三种情况 // 对于Date等引用类型的数据,需要考虑调用构造函数重新构造,直接赋值依然会有引用问题(不是真正的clone引用变量)
// 以Date为例
if (src instanceof Date) {
var clone = new Date(src.getDate());
return clone;
} // 对于数组,需要遍历,这样可以保证在在Array对象上扩展的属性也可以正确复制
if (isArray(src)) {
var clone = [];
for (var i = 0; i < src.length; i++) {
clone[i] = cloneObject(src[i]);
}
return clone;
} // 对于其他object,同样也需要遍历
if (src instanceof Object) {
var clone = {};
for (var key in src) {
if (src.hasOwnProperty(key)) { // 忽略掉继承属性,只取属于它本身的属性
clone[key] = cloneObject(src[key]);
}
}
return clone;
}
}

4. 对数组进行去重操作,只考虑数组中元素为数字或字符串,返回一个去重后的数组。

// 普通实现
function uniqArray(arr) {
if (arr.length < 2) return arr;
for (var i = 0; i < arr.length - 1; i++) {
for (var j = i + 1; j < arr.length; j++) {
if (arr[i] == arr[j]) {
arr.splice(j, 1); // 数组的splice方法:删除数组中的某一个元素
}
}
}
return arr;
} // 利用对象的keys方法进行筛选:把元素作为属性添加到对象中,重复的话自然不会有影响(类似桶排思想)
function uniqArray2(arr) {
var obj = {};
for (var i = 0, len = arr.length; i < len; i++) {
obj[arr[i]] = true;
}
return Object.keys(obj);
}

5. 实现一个简单的trim函数,用于去除一个字符串,头部和尾部的空白字符。

通过循环,以及字符串的一些基本方法,分别扫描字符串str头部和尾部是否有连续的空白字符,并且删掉他们,最后返回一个完成去除的字符串。

function simpleTrim(str) {
// 关键在于找到字符串中间非空的部分的下标值
var head = 0, tail = str.length - 1;
while(str[head] == ' ') head++;
while(str[tail] == ' ') tail--;
return str.substring(head, tail + 1); // substring方法不包括tail下标
}

6. 通过正则表达式完成题5

首先正则表达式形如:/ .... /

然后里面有一些匹配符:\d 数字,\w 字母数字下划线,\s 空格

还有一些特殊符号:^ 开头,$ 结尾,| 或者

还有 / .... / 后面有时还会跟一个字母:g 全局,i 忽略大小写

function trim(str) {
// 对字符串的正则表达式处理通常用到replace方法
// str.replace(re, newSub):将字符串被re匹配到的部分,用newSub来代替。
return str.replace(/^\s+|\s+$/g, '');
}

上面的正则表达式:以\s(即空格)开头或结尾,+号表示一个或多个。

// 判断是否为邮箱地址
function isEmail(emailStr) {
return emailStr.search(/^[a-z0-9]([-_\.]?[a-z0-9]+)*@([-_]?[a-z0-9]+)+[\.][a-z]{2,7}([\.][a-z]{2})?$/i) !== -1;
} // 判断是否为手机号
function isMobilePhone(phone) {
phone = phone + '';
return phone.search(/^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/) !== -1;
}

DOM

1. 题目:获取element相对于浏览器窗口的位置,返回一个对象{x, y}

以下是一些常用宽高度的属性:

宽度
元素所占宽度包含 内容区宽度 内边距padding 边框的宽度
简单来说:padding是一个元素所占大小的概念,margin是个定位的概念。

偏移量 offset
offsetLeft表达的是元素所占区域的左边缘到父元素的左边缘,即元素的左外边框到包含元素的左内边框的像素距离

页面的真实高度、宽度
document.documentElement.scrollHeight
document.documentElement.scrollWidth
document.documentElement 是一个只读属性,返回文档对象(document)的根元素(例如,HTML文档的 <html> 元素)。

可视区域的高度
document.documentElement.clientHeight
如果页面是一个竖向页面(一般而言),可视区域的宽度和页面的宽度是一样的,使用scrollWidth即可。另外还有window.innerHeight也可以求可视区域高度,但不兼容低版本IE浏览器。使用的时候可以用兼容写法:

var pageHeight = window.innerHeight || document.documentElement.clientHeight;
var pageWidth = window.innerWidth || document.documentElement.clientWidth;

元素的真实高度、宽度
offsetWidth、offsetHeight是一个经常使用的值,该值真实的反映了元素所占空间的大小,而width,height属性仅仅表达了内容区。

获取元素的绝对位置

网页元素的绝对位置,指该元素的左上角相对于整张网页左上角的坐标。

首先,每个元素都有offsetTop和offsetLeft属性,表示该元素的左上角与父容器(offsetParent对象)左上角的距离。所以,只需要将元素本身的offsetTop和offsetLeft分别和其所有父容器的offsetTop和offsetLeft相加(循环,往上遍历),就可以得到该元素的绝对坐标。

获取元素的相对位置

网页元素的相对位置,指该元素左上角相对于浏览器窗口左上角的坐标。

有了绝对位置以后,获得相对位置就很容易了,只要将绝对坐标减去页面的滚动条滚动的距离就可以了。滚动条滚动的垂直距离,是document对象的scrollTop属性;滚动条滚动的水平距离是document对象的scrollLeft属性。

题目所要求的就是获取元素的相对位置。

// 获取element相对于浏览器窗口的位置,返回一个对象{x, y}
function getPosition(element) {
var x = 0;
var y = 0;
var currentElement = element; // 从目标元素开始往上遍历 while (currentElement !== null) {
x += currentElement.offsetLeft;
y += currentElement.offsetTop;
currentElement = currentElement.offsetParent;
} // 为了兼容,documentElement、body这两个值总会有一个恒为0
var scrollLeft = document.documentElement.scrollLeft + document.body.scrollLeft;
var scrollTop = document.documentElement.scrollTop + document.body.scrollTop; x -= scrollLeft;
y -= scrollTop; return {
x: x,
y: y
};
}

2. 实现一个简单的query

// 实现一个简单的Query
function $(selector) {
// 思路是取出第一个字符,然后分情况去获取不同的元素
var element = null;
var prefix = selector.charAt(0);
switch(prefix) {
case '#':
element = document.getElementById(selector.substring(1));
break;
case '.':
element = document.getElementsByClassName(selector.substring(1));
break;
default:
element = document.getElementsByTagName(selector);
}
return element;
} console.log($("#adom"));
console.log($("div"));
console.log($(".classa"));

事件

事件冒泡:事件开始由最具体的元素(具体目标)接收,然后逐级向上传播到较为不具体的节点,当我点击一个按钮,click事件不断往上冒泡(button→body→html→Document),相当于从下往上每个都被click了一次。

事件捕获:和冒泡相反,事件从不太具体的节点开始接收事件,而最具体的节点最后接收。

DOM2级事件:三个阶段:捕获→目标→冒泡。

事件处理函数:也就是常说的listener,这个函数有一些独到之处:

  1. function(e) {...} 参数e称为事件对象,是浏览器将event对象作为参数传进来的,在IE中event对象作为window对象的一个属性存在
  2. 在这个函数里,this值等于事件的目标元素

以前常用的 btn.onclick = function() {...} 的做法是DOM0级的指定事件处理程序的方式

DOM2级事件定义了两个方法:addEventListener和removeEventListener,三个参数分别是:要处理的事件名,事件处理函数,一个布尔值(true表示在捕获阶段调用事件处理程序,false则是冒泡阶段,默认为false)

事件处理函数 function(e) {...} 的参数e,即事件对象e,e.target表示的是事件的真正目标(比如上述加粗例子中的按钮),可以通过 e.target == this 来判断当前对象和事件的真正目标是否相同(避免冒泡带来的误差),或者使用e.stopPropagation()来阻止事件的传播。

// 给一个element绑定一个针对event事件的响应,响应函数为listener
function addEvent(element, event, listener) {
element.addEventListener(event, listener);
} // 移除element对象对于event事件发生时执行listener的响应
function removeEvent(element, event, listener) {
element.removeEventListener(event, listener);
} // 实现对click事件的绑定
function addClickEvent(element, listener) {
addEvent(element, "click", listener);
} // 实现对于按Enter键时的事件绑定
function addEnterEvent(element, listener) {
// 键盘事件一般来说element是window
addEvent(element, "keydown", function (e) {
var event = e || window.event; // window.event是IE写法
if (event.keyCode == 13) {
// 这里要注意调用listener函数要将this绑定到element上,因为listener里的this是element,参数是event
listener.call(element, event);
}
})
} addClickEvent($(".classa")[0], function () {
console.log(this); // 元素".classa"
}); addEnterEvent(window, function () {});

事件代理(事件委托)

事件处理函数绑定在父元素上,当子元素发生事件时会冒泡到父元素,导致该事件处理函数触发,然后调用该事件处理函数的时候重新把this绑定回子元素上。

// 事件代理(事件委托)
// 实现对element中所有标签为tag的子元素绑定事件(优点:把listener绑定在父元素上,减少DOM访问次数和listener数量)
// 原理:事件冒泡
function delegateEvent(element, tag, eventName, listener) {
$.on(element, eventName, function (e) {
var event = e || window.event;
var target = event.target || event.srcElement;
if (target && target.tagName == tag.toUpperCase()) { // element.tagName得到元素标签名(大写)
listener.call(target, event);
}
});
}

IFE 2015_spring task0002 自学记录的更多相关文章

  1. 【Unity3D自学记录】判断物体是否在镜头内

    判断物体是否在镜头内. 其实很简单的方法 代码如下: using UnityEngine; using System.Collections; public class DJH_IsRendering ...

  2. 【Unity3D自学记录】Unity3D网络之Socket聊天室初探

    首先创建一个服务端程序,这个程序就用VS的控制台程序做即可了. 代码例如以下: using System; using System.Collections.Generic; using System ...

  3. 【Unity3D自学记录】可视化对照十多种排序算法(C#版)

    在这篇文章中.我会向大家展示一些排序算法的可视化过程.我还写了一个工具.大家可对照查看某两种排序算法. 下载源代码 – 75.7 KB 下载演示样例 – 27.1 KB 引言 首先,我觉得是最重要的是 ...

  4. 【Unity3D自学记录】利用代码改动图片属性(Inspector)

    这段时间一直都在打包资源,然后每次导入都要改图片的属性.真是麻烦,所以一直在寻找一键改动而且打包的方法. 最终让我找到了,太坑人了. 依据自己的需求改代码哦,相信大家都能看明确. 核心部分: Text ...

  5. HTML5 表单自学记录

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. 【Unity3D自学记录】Unity3D之自制小钟表

    今天来写一个小钟表,事实上非常easy,就运用到了欧拉角. 首先创建时钟.分钟.秒钟以及4个点(12点.3点.6点.9点)偷懒了~~没弄那么多点. 时钟.分钟.秒钟这三个父级的中心一定要注意,我们旋转 ...

  7. 【Unity3D自学记录】鼠标移动三维物体

    创建一个脚本.例如以下: using UnityEngine; using System.Collections; public class OnMouse : MonoBehaviour { IEn ...

  8. selenium自学记录2014.12.26

    现在还是有点病急乱投医的感觉,不知道到底该从何学起,到底怎么学 手头上有的资料是 <零成本实现Web自动化测试-基于Selenium和Bromine> <Selenium测试实践-基 ...

  9. node.js第一次

    随着时代的变迁,日月星辰轮回,不断的有新的事物被创造于世,作为在这个世界活着的前端工程崽的我,最近又接触了一门新手艺“node.js”.自从它2009年诞生至今,被很多前端推崇,我起步已经晚了,还好它 ...

随机推荐

  1. Create a Group Policy Central Store

    一.How to create a Group Policy Central Store You have downloaded or created your own Group Policy Ad ...

  2. JS去遍历Table的所有单元格中的内容

    用JS去遍历Table的所有单元格中的内容,可以用如下JS代码实现 function GetInfoFromTable(tableid) { var tableInfo = ""; ...

  3. SQL中的函数 •Aggregate 函数 •Scalar 函数

    合计函数  :Aggregate是针对一系列值的操作,返回一个单一的值 Scalar 函数是针对一个单一的值的操作,返回基于输入值的一个单一值 合计函数: AVG()返回某列的平均值:COUNT()返 ...

  4. AttachThreadInput

    BOOL WINAPI AttachThreadInput( _In_  DWORD idAttach, _In_  DWORD idAttachTo, _In_  BOOL fAttach ); i ...

  5. ArcGIS api for silverlight 禁用默认浏览操作

    ArcGIS api for silverlight 的mapcontrol中提供了一系列的默认浏览工具选项(default navigation options),如下表所示, 那么如何禁用这些默认 ...

  6. 用jq实现鼠标移入按钮背景渐变其他的背景效果

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. js中window.open的参数及注意

    IE9下使用window.open时需要注意name参数值不能有"-"出现,否则会出现脚本错误,IE9以及版本测试没有问题   window.open(URL,name,specs ...

  8. sql server性能调优

    转自:https://www.cnblogs.com/woodytu/tag/%E6%80%A7%E8%83%BD%E8%B0%83%E4%BC%98%E5%9F%B9%E8%AE%AD/defaul ...

  9. Hadoop2.0中单点故障解决方案总结---老董

    Hadoop 1.0内核主要由两个分支组成:MapReduce和HDFS,众所周知,这两个系统的设计缺陷是单点故障,即MR的JobTracker和HDFS的NameNode两个核心服务均存在单点问题, ...

  10. python s12

    logging模块 很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误.警告等信息输出,python的logging模块提供了标准的日志接口,你可以通过它存储各种格式 ...