hoisting
http://openwares.net/js/javascript_declaration_hoisting.html
map、reduce
练习:不要使用JavaScript内置的parseInt()函数,利用map和reduce操作实现一个string2int()函数:
return [].slice.call(s).map(function(x){return x/1}).reduce(function(x, y){return x*10 + y})
JS隐式转换
Javascript 在遇到算数运算符(-
、*
、/
和%
)的时候会在运算之前将参与运算的双方转换成数字。
注意+
加号特殊哦~
练习:希望利用map()把字符串变成整数
var arr = ['1', '2', '3'];
var r;
r = arr.map(parseInt);
但是结果却是[1, NaN, NaN]
参考Array.prototype.map
原因是:
arr.map(callback[, thisArg])
Parameters
- callback
Function that produces an element of the new Array, taking three arguments:
-- currentValue
The current element being processed in the array.也就是array中需要处理的元素
-- index
The index of the current element being processed in the array.上面那个元素在array中的index
-- array
The array map was called upon.
- thisArg
Optional. Value to use as this when executing callback. Default value is the Window object
callback函数传递三个参数currentValue, index,array,而ParseInt需要两个参数,PareseInt会把map传过来的第二个参数index 0,1,2作为数制参数十进制,一进制,二进制,因此1被转为1 ,2和3 因为不符合一进制,二进制所以返回NaN
filter
filter也是一个常用的操作,它用于把Array的某些元素过滤掉,然后返回剩下的元素。
和map()类似,Array的filter()也接收一个函数。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。
例如,把一个Array中的空字符串删掉,可以这么写:
var arr = ['A', '', 'B', null, undefined, 'C', ' '];
var r = arr.filter(function (s) {
return s && s.trim(); // 注意:IE9以下的版本没有trim()方法
});
r; // ['A', 'B', 'C']
arguments
JavaScript还有一个免费赠送的关键字arguments
,它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。即使函数不定义任何参数,还是可以拿到参数的值:
function abs() {
if (arguments.length === 0) {
return 0;
}
var x = arguments[0];
return x >= 0 ? x : -x;
}
abs(); // 0
abs(10); // 10
abs(-9); // 9
实际上arguments
最常用于判断传入参数的个数。你可能会看到这样的写法:
// foo(a[, b], c)
// 接收2~3个参数,b是可选参数,如果只传2个参数,b默认为null:
function foo(a, b, c) {
if (arguments.length === 2) {
// 实际拿到的参数是a和b,c为undefined
c = b; // 把b赋给c
b = null; // b变为默认值
}
// ...
}
要把中间的参数b变为“可选”参数,就只能通过arguments判断,然后重新调整参数并赋值。
例子:
实现函数useArguments
,返回所有调用参数相加后的结果。
你可能会酱紫写。但这是错的!
function useArguments() {
return arguments.reduce(function(x, y){
return x+y;
})
}
注意:arguments类似Array但它不是一个Array,所以它的原型上没有reduce方法,我们要做的就是让arguments来调用Array.prototype上的方法(用到call或者apply),或者干脆把arguments变为数组。
如何把一个伪数组转变成真正的数组呢?
Array.prototype.slice.call(arguments)
我们可以这样写
function useArguments() {
return Array.prototype.slice.call(arguments).reduce(function(x,y){
return x+y;
})
}
//或者
function useArguments() {
return [].slice.call(arguments).reduce(function(x,y){
return x+y;
})
}
或者让arguments来调用Array.prototype上的方法。
function useArguments() {
return [].reduce.call(arguments, function(x,y){
return x+y;
})
}
因为slice
,reduce
都是Array.prototype上的方法,用call或者apply来改变当前对象为arguments再调用即可。
PS: concat函数用于连接两个数组,返回新的连接好的数组,而不会改变原数组。
函数的长度
函数的长度也就是函数的length属性,指的是函数的形参的个数,不是传入的参数个数哦。
function test1(){
console.log(test1.length);
}
test1(a,b,c); // 0
柯里化(currying)
柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且接受余下的参数且返回结果。
题目描述
已知 fn 为一个预定义函数,实现函数 curryIt,调用之后满足如下条件:
1、返回一个函数 a,a 的 length 属性值为 1(即显式声明 a 接收一个参数)
2、调用 a 之后,返回一个函数 b, b 的 length 属性值为 1
3、调用 b 之后,返回一个函数 c, c 的 length 属性值为 1
4、调用 c 之后,返回的结果与调用 fn 的返回值一致
5、fn 的参数依次为函数 a, b, c 的调用参数
var fn = function (a, b, c) {return a + b + c};
curryIt(fn)(1)(2)(3); //6
caller和callee
答案:(目前不太懂,貌似不让用callee属性)
function curryIt(fn) {
//获取fn参数的数量
var n = fn.length;
//声明一个数组args
var args = [];
//返回一个匿名函数
return function(arg){
//将curryIt后面括号中的参数放入数组
args.push(arg);
//如果args中的参数个数小于fn函数的参数个数,
//则执行arguments.callee(其作用是引用当前正在执行的函数,这里是返回的当前匿名函数)。
//否则,返回fn的调用结果
if(args.length < n){
return arguments.callee;
}else return fn.apply("",args);
}
}
Number.toString()方法
Number类型的toString()方法比较特殊,有默认模式和基模式两种。
//默认模式的例子:
var num1 = 10;
var num2 = 10.0;
alert(num1.toString());//输出"10"
alert(num2.toString());//输出"10"
//无论你用什么表示法声明数字,默认模式只是按十进制返回。
//基模式的例子:
var num1 = 10;
alert(num1.toString(2));//输出1010
alert(num1.toString(8));//输出12
alert(num1.toString(16));//输出A
全局对象的parseInt()方法和parseFloat()方法
parseInt() 函数可解析一个字符串,并返回一个整数。
1、解析字符串,直到不能解析为止
2、进制转化中,解析字符串,直到不能解析为止
document.write(parseInt("123") + "
"); //123
document.write(parseInt("1abc23") + "
"); //1
document.write(parseInt("123abc") + "
"); //123
document.write(parseInt("abc") + "
"); //NaN
document.write(parseInt("100",2) + "
"); //4,以二进制形式解析
document.write(parseInt("123",2)); //1,因为2、3不能解析
parseFloat
二进制转换
题目:将给定数字转换成二进制字符串。如果字符串长度不足 8 位,则在前面补 0 到满8位。
function convertToBinary(num) {
var tmp = num.toString(2).split('');
while(tmp.length < 8){
[].unshift.call(tmp, 0)
//tmp.unshift(0);
}
return tmp.join('');
}
Array.unshfit()
unshift()
方法可向数组的开头添加一个或更多元素,并返回新的长度请注意,unshift() 方法不创建新的创建,而是直接修改原有的数组。
String.split()
split()
方法用于把一个字符串分割成字符串数组。这样才能通过call使用数组原型链上的方法啊。
Array.join()
Array.join
执行的操作与String.split()
执行的操作是相反的。join() 方法用于把数组中的所有元素放入一个字符串
Array.slice()
slice(0,-1)如果是负数,那么它规定从数组尾部开始算起的位置。也就是说,-1 指最后一个元素,-2 指倒数第二个元素,以此类推。http://www.w3school.com.cn/jsref/jsref_slice_array.asp
Array.splice()
splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目。该方法会改变原始数组。
http://www.w3school.com.cn/jsref/jsref_splice.asp
arrayObject.splice(index,howmany,item1,.....,itemX)
splice() 方法可删除从 index 处开始的零个或多个元素,并且用参数列表中声明的一个或多个值来替换那些被删除的元素。
如果从 arrayObject 中删除了元素,则返回的是含有被删除的元素的数组。
Number.toFixed()
精确小数到多少位http://www.w3school.com.cn/jsref/jsref_tofixed.asp
遍历属性
function iterate(obj) {
var result = [];
for (var key in obj){
if(obj.hasOwnProperty(key)){
result.push(key+": "+obj[key])
}
}
return result;
}
几条规则
- 不要使用
new Number()
、new Boolean()
、new String()
创建包装对象; - 用
parseInt()
或parseFloat()
来转换任意类型到number; - 用
String()
来转换任意类型到string,或者直接调用某个对象的toString()
方法; - 通常不必把任意类型转换为boolean再判断,因为可以直接写if (myVar) {...};
- typeof操作符可以判断出number、boolean、string、function和undefined;
- 判断Array要使用
Array.isArray(arr)
; - 判断null请使用
myVar === null
; - 判断某个全局变量是否存在用
typeof window.myVar === 'undefined'
; - 函数内部判断某个变量是否存在用
typeof myVar === 'undefined'
。
任何对象都有toString()方法吗?null和undefined就没有!确实如此,这两个特殊值要除外,虽然null
还伪装成了object类型。
number对象调用toString()报SyntaxError:
123.toString(); // SyntaxError
遇到这种情况,要特殊处理一下:
123..toString(); // '123', 注意是两个点!(123).toString(); // '123'
不要问为什么,这就是JavaScript代码的乐趣!
Array中的sort()
如果调用该方法时没有使用参数,将按字母顺序对数组中的元素进行排序,说得更精确点,是按照字符编码的顺序进行排序。要实现这一点,首先应把数组的元素都转换成字符串(如有必要),以便进行比较。
//请填充代码,使mySort()能使传入的参数按照从小到大的顺序显示出来。
function mySort() {
var tags = new Array();//使用数组作为参数存储容器
// 请补充你的代码
return tags;//返回已经排序的数组
}
var result = mySort(50,11,16,32,24,99,57,100);/传入参数个数不确定
console.info(result);//显示结果
如果只是简单的添加了这句
tags = [].slice.call(arguments).sort();
输出的结果为[100, 11, 16, 24, 32, 50, 57, 99]
,100居然排在了最前面,因为sort默认是按照字符编码的顺序进行排序的。
如果想按照其他标准进行排序,就需要提供比较函数,该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。比较函数应该具有两个参数 a 和 b,其返回值如下:
若 a 小于 b,在排序后的数组中** a 应该出现在 b 之前,则返回一个小于 0 的值**。
若 a 等于 b,则返回 0。
若 a 大于 b,则返回一个大于 0 的值。
//正确代码
tags = Array.prototype.slice.call(arguments);
tags.sort(function(a,b){return a-b;});
升序:则参数方程返回小于0;降序:则返回值大于0;
js跨域
http://www.cnblogs.com/2050/p/3191744.html
事件代理
//兼容浏览器版本差异
function addEvent(element, event, listener) {
if (element.addEventListener) {
element.addEventListener(event, listener, false);
}
else if (element.attachEvent) {
element.attachEvent("on" + event, listener);
}
else {
element["on" + event] = listener;
}
}
//事件代理
function delegateEvent (element, tag, eventName, listener){
addEvent(element, eventName, function(e){
//这里的参数e就是前面那个event参数的对象,自动传入
e = e || window.event;
var target = e.target || e.srcElement;
console.log("event", e);
//event: click { target: