javascript实用

麋鹿麋鹿迷了路 2020-07-05

JavaScript引擎是一个事件驱动的执行引擎,代码总是以单线程执行,而回调函数的执行需要等到下一个满足条件的事件出现后,才会被执行。

1. JavaScript不区分整数和浮点数,统一用Number表示。

NaN:表示Not a Number,当无法计算结果时用NaN表示。

Infinity:表示无限大,当数值超过JavaScriptNumber所能表示的最大值时。

2. 比较运算符有=====,不要使用==比较,应坚持使用===比较。

3. NaN和所有其他值都不相等,包括它自己:NaN === NaN // false

唯一能判断NaN的方法是通过isNaN()函数:isNaN(NaN) // ture

4. null表示一个“空”值,它和0以及空字符串””不同,0是一个数值,””表示长度为0的字符串,而null表示“空”。

undefined表示未定义。

大多数情况下,都应该用nullundefined仅仅在判断函数参数是否传递的情况下有用。

5. Javascript数组可以包括任意数据类型,元素之间用逗号(,)隔开。

除直接用[]创建数组外,还可以通过Array()函数创建数组,new Array(1, 2, 3)

通过length属性获取数组长度,arr.length

注意:直接给Arraylength赋一个新的值会导致Array大小的变化。如果通过索引赋值时,索引超过了范围,同样会引起array大小的变化。

可通过join()方法把数组的每个元素用指定的字符串连接起来,然后返回连接后的字符串。

6. 变量名是大小写英文、数字、$_的组合,且不能用数字开头。

同一个变量可以反复赋值,而且可以是不同类型的变量,但是注意只能用var申明一次。

7. 对象是一种无序的集合数据类型,由若干键值对组成。用{...}表示一个对象,键值对以xxxxxx形式申明,用逗号隔开。

键是对象的属性,访问属性通过点号(.)访问,所有属性都是字符串,值可以是任意类型。

如果属性名包含特殊字符,必须用’’括起来,且不可用点号访问,必须用[]访问。

删除属性用delete

检测对象是否有某一属性,用in操作符。不过要小心,如果in判断一个属性存在,这个属性不一定是对象的,可能是该对象集成得到的。

要判断一个属性是否是对象自身拥有的,而不是集成得到的,可以用hasOwnProperty()方法。

8. for循环的一个变体是for...in循环,可以把一个对象的属性循环出来:

var o = {
    name: ‘Jack‘,
    age: 20,
    city: ‘Beijing‘
};
for (var key in o) {
    if (o.hasOwnProperty(key)) {
        console.log(key); // ‘name‘, ‘age‘, ‘city‘
    }
}

9. Map是一组键值对的结构,具有极快的查找速度,map的键可以是任意数据类型。初始化map需要一个二维数组,或者直接初始化一个空的。

var m = new Map([[‘Wang’, 96], [‘Li’, 94’], [‘Yu’, 80]]);
m.get(‘wang’)
m.set(‘wang’, 80)
m.delete(‘wang’)

10. set是一组key的集合,不存储valuekey不能重复(重复key自动过滤)

创建一个set,需要提供一个array最为输入,或者直接创建一个空的set。

11. Arraymapset都属于iterable类型,通过for... of循环遍历,只循环集合本身的元素。

Iterable内置forEach方法,它接收一个函数,每次迭代就自动回调该函数。

var a = [‘a‘, ‘b‘, ‘c‘]

a.forEach(function (value, index, array){
    console.log(value + ‘, index= ‘ + index + ‘, array: ‘ + array)
}

数组的回调函数,参数依次是元素值,索引和对象本身。

Set和数组类似,但set没有索引,因此回调函数的前两个参数都是元素本身。

Map的回调函数参数依次为valuekeymap本身。

12. 函数如果没有return语句,函数执行完毕后返回结果undefined

13. JavaScript允许传入任意个参数而不影响调用,参数的使用由函数内部确定。

abs() // 返回NaN

此时abs(x)函数的参数x将收到undefined,计算结果为NaN

要避免收到undefined,可以对参数进行检查:

function abs(x) {
    if (typeof x !== ‘number‘) {
        throw ‘Not a number‘;
    }
    if (x >= 0) {
        return x;
    } else {
        return -x;
    }
}

14. 关键字arguments只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。Arguments类似Array但它不是一个ArrayArguments常用语判断传入参数的个数arguments.length

15. ES6引入rest参数,表征剩余参数:function foo(a, b, ...rest)

Rest参数只能写在最后,前面用...标识,多余的参数以数组形式交给变量rest。如果传入的参数连正常定义的参数都没有填满,rest参数会接收一个空数组(不是undefined)。

16. 函数定义时会扫描整个函数体的语句,把所有申明的变量“提升”到函数的顶部,但不会提升变量的赋值(未定义的变量默认定义为undefined)。

function foo(){
    var x = y
    console.log(x)    // undefined
    var y = {name: "wang", id: "1"}
    console.log(y)   // {name: ‘wang’, id: ‘1’}
}

foo()

据此,应严格遵守“在函数内部首先申明所有变量”规则,通过var首先申明变量。

17. 为了减少命名冲突,应该把自己的所有变量和函数全部绑定到一个全局变量中,从而减少与全局变量window等的冲突,如jQueryunderscore都是这样做的。

18. 作用域:JavaScript的变量作用域实际上是函数内部,在for循环等语句块中无法定义局部作用域的变量。ES6引入关键字let来代替var申明一个块级作用域变量。

for (let i=0; i < 100; i++){sum +=i}

19. ES6引入关键字const定义常量,constlet都是块级作用域,常量一般用大写字母。

20. 在一个对象中绑定的函数是对象的方法。在方法内部,this是一个特殊变量,始终指向当前对象,且只在对象的顶层函数中指向对象,否则执行全局对象windowundefined,报TypeError错误。

21. 字符串操作函数

Split:"house".split(‘‘) // [‘h’, ‘o’, ‘u’, ‘s’, ‘e’]

22. 高阶函数:函数的参数中包含函数。

23. map/reduce MapReduce: Simplified Data Processing on Large Clusters

Mapreduce都是array的方法,参数都是函数。

[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)

function pow(x){
    return x * x
}
function sum(x, y){
    return x + y
}
var results = [1, 2, 3, 4].map(pow)   // [1, 4, 9, 16]
var resultsRes = [1, 2, 3, 4].reduce(sum) // 10

24. 闭包:函数返回函数。

注意:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

25. 箭头函数相当于匿名函数,并且简化了函数定义:

x => x*x

x => {return x * x }

返回对象: x => ({foo: x})

箭头函数的this总是指向词法作用域,也就是外层调用者obj

26. 在JavaScript中,所有代码都是单线程执行的。若要异步执行可以用Promise对象,Promise可以在异步执行流程中,把执行代码和处理结果代码清晰分离。

new Promise(function (reslove, reject){
    console.log("this is promise program")
    var timeout = Math.random()*2
    console.log(‘set timeout to : ‘ + timeout + ‘ second‘)
    setTimeout(function(){
        if (timeout < 1){
            console.log(‘call resolve()...‘)
            reslove(‘200 OK‘)
        } else {
            console.log(‘call reject()...‘)
            reject("timeout")
        }
    }, 1000)
}).then(function(a){
    console.log(a)  // resolve() return: 200 OK
}).catch(function(b){
    console.log(b)  // reject() return: timeout
}
job1.then(job2).then(job3).catch(handleError);

Job1job2job3串行执行任务。

并行执行任务用Promise.all()

var p1 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 500, ‘P1‘);
});
var p2 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 600, ‘P2‘);
});// 同时执行p1和p2,并在它们都完成后执行then:
Promise.all([p1, p2]).then(function (results) {
    console.log(results); // 获得一个Array: [‘P1‘, ‘P2‘]
});

同时向两个URL读取用户的个人信息,只需要获得先返回的结果即可,用Promise.race()实现:(执行相应时间短的,其他丢弃)

var p1 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 500, ‘P1‘);
});
var p2 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 600, ‘P2‘);
});
Promise.race([p1, p2]).then(function (result) {
    console.log(result); // ‘P1‘
});

27. JavaScript有一个标准的Error对象表示错误,还有从Error派生的TypeErrorReferenceError等错误对象。我们在处理错误时,可以通过catch(e)捕获的变量e访问错误对象。

28. 涉及到异步代码,无法在调用时捕获错误,原因就是在捕获的当时,回调函数并未执行。类似的,当我们处理一个事件时,在绑定事件的代码处,无法捕获事件处理函数的错误。应在错误发生的函数中捕获错误。哪里出错哪里才能try-catch捕获。

29. Underscore提供了一套完善的函数式编程接口,把自身绑定到唯一的全局变量_上。

参考:

1. Javascript教程 廖雪峰

相关推荐