数据类型
在 JavaScript 中有 5 中不同的数据类型:
string
number
boolean
object
function
3 种对象类型:
Object
Date
Array
2 个不包含任何值的数据类型:
null
undefined
你可以使用 typeof 操作符来查看 JavaScript 变量的数据类型。
实例
typeof "John" // 返回 string
typeof 3.14 // 返回 number
typeof NaN // 返回 number
typeof false // 返回 boolean
typeof [1,2,3,4] // 返回 object
typeof {name:'John', age:34} // 返回 object
typeof new Date() // 返回 object
typeof function () {} // 返回 function
typeof myCar // 返回 undefined (if myCar is not declared)
typeof null // 返回 object
请注意:
NaN 的数据类型是 number
数组(Array)的数据类型是 object
日期(Date)的数据类型为 object
null 的数据类型是 object
未定义变量的数据类型为 undefined
如果对象是 JavaScript Array 或 JavaScript Date ,我们就无法通过 typeof 来判断他们的类型,因为都是 返回 Object。
解决方法:
判断是否是数组
myArray.constructor.toString().indexOf("Array") > -1;
判断是否是日期
myDate.constructor.toString().indexOf("Date") > -1;
arguments caller callee
arguments 的完整语法如下:
[function.]arguments[n]
参数function :选项。当前正在执行的 Function 对象的名字。 n :选项。要传递给 Function 对象的从0开始的参数值索引。
在一个函数调用另一个函数时,被调用函数会自动生成一个caller属性,指向调用它的函数对象。如果该函数当前未被调用,或并非被其他函数调用,则caller为null。
当函数被调用时,它的arguments.callee对象就会指向自身,也就是一个对自己的引用。
由于arguments在函数被调用时才有效,因此arguments.callee在函数未调用时是不存在的(即null.callee),且解引用它会产生异常。
var foo = function bar() {
// statements go here
};
在这个函数体内,以下的语句是等价的:
bar()
arguments.callee()
foo()
嵌套函数和闭包
你可以在一个函数里面嵌套另外一个函数。嵌套(内部)函数是容器(外部)函数的私有成员。它自身也形成了一个闭包。一个闭包是一个可以自己拥有独立的环境与变量的的表达式(通常是函数)。
既然嵌套函数是一个闭包,就意味着一个嵌套函数可以继承容器函数的参数和变量。换句话说,内部函数包含外部函数的作用域。
可以总结如下:
内部函数只可以在外部函数中访问
内部函数形成了一个闭包:它可以访问外部函数的参数和变量,但是外部函数却不能使用它的参数和变量
function outside(x) {
function inside(y) {
return x + y;
}
return inside;
}
// Think of it like: give me a function that adds 3 to whatever you give it
fn_inside = outside(3);
console.log(fn_inside);
result = fn_inside(5); // returns 8
console.log(result);
result1 = outside(3)(5); // returns 8
console.log(result1)
保存变量
注意到上例中inside被返回时x是怎么被保留下来的。一个闭包必须保存它可见作用域中所有的参数和变量。因为每一次调用传入的参数都可能不同,每一次对外部函数的调用都实际上重新创建了一遍这个闭包。只有当inside的返回值没有再被引用时,内存才会被释放。
这与存储在其他对象的引用不同,而且通常是不太明显的,因为并不能直接设置引用,且不能检查(inspect)它们。
细节
1、switch 语句会使用恒等计算符(===)进行比较
2、字符串断行需要使用反斜杠(\)
3、
JavaScript 不支持使用名字来索引数组,只允许使用数字索引。
实例
var person = [];
person[0] = "John";
person[1] = "Doe";
person[2] = 46;
var x = person.length; // person.length 返回 3
var y = person[0]; // person[0] 返回 "John"
在 JavaScript 中, 对象 使用 名字作为索引。
如果你使用名字作为索引,当访问数组时,JavaScript 会把数组重新定义为标准对象。
执行这样操作后,数组的方法及属性将不能再使用,否则会产生错误:
实例
var person = [];
person["firstName"] = "John";
person["lastName"] = "Doe";
person["age"] = 46;
var x = person.length; // person.length 返回 0
var y = person[0]; // person[0] 返回 undefined
4、
Undefined 不是 Null
在 JavaScript 中, null 用于对象, undefined 用于变量,属性和方法。
对象只有被定义才有可能为 null,否则为 undefined。
如果我们想测试对象是否存在,在对象还没定义时将会抛出一个错误。
错误的使用方式:
if (myObj !== null && typeof myObj !== "undefined")
正确的方式是我们需要先使用 typeof 来检测对象是否已定义:
if (typeof myObj !== "undefined" && myObj !== null)
5、JavaScript 闭包
还记得函数自我调用吗?该函数会做什么?
实例
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
})();
add();
add();
add();
// 计数器为 3
实例解析
变量 add 指定了函数自我调用的返回字值。
自我调用函数只执行一次。设置计数器为 0。并返回函数表达式。
add变量可以作为一个函数使用。非常棒的部分是它可以访问函数上一层作用域的计数器。
这个叫作 JavaScript 闭包。它使得函数拥有私有变量变成可能。
计数器受匿名函数的作用域保护,只能通过 add 方法修改。
6、事件冒泡或事件捕获?
事件传递有两种方式:冒泡与捕获。
事件传递定义了元素事件触发的顺序。 如果你将 <p> 元素插入到 <div> 元素中,用户点击 <p> 元素, 哪个元素的 "click" 事件先被触发呢?
在 冒泡 中,内部元素的事件会先被触发,然后再触发外部元素,即: <p> 元素的点击事件先触发,然后会触发 <div> 元素的点击事件。
在 捕获 中,外部元素的事件会先被触发,然后才会触发内部元素的事件,即: <div> 元素的点击事件先触发 ,然后再触发 <p> 元素的点击事件。
addEventListener() 方法可以指定 "useCapture" 参数来设置传递类型:
addEventListener(event, function, useCapture);
默认值为 false, 即冒泡传递,当值为 true 时, 事件使用捕获传递。
实例
document.getElementById("myDiv").addEventListener("click", myFunction, true);
跨浏览器解决方法:
var x = document.getElementById("myBtn");
if (x.addEventListener) { // 所有主流浏览器,除了 IE 8 及更早版本
x.addEventListener("click", myFunction);
} else if (x.attachEvent) { // IE 8 及更早版本
x.attachEvent("onclick", myFunction);
}
7、Window 尺寸
有三种方法能够确定浏览器窗口的尺寸(浏览器的视口,不包括工具栏和滚动条)。
对于Internet Explorer、Chrome、Firefox、Opera 以及 Safari:
window.innerHeight - 浏览器窗口的内部高度
window.innerWidth - 浏览器窗口的内部宽度
对于 Internet Explorer 8、7、6、5:
document.documentElement.clientHeight
document.documentElement.clientWidth
或者
document.body.clientHeight
document.body.clientWidth
实用的 JavaScript 方案(涵盖所有浏览器):
实例
var w=window.innerWidth
|| document.documentElement.clientWidth
|| document.body.clientWidth;
var h=window.innerHeight
|| document.documentElement.clientHeight
|| document.body.clientHeight;