JS笔记
js代码嵌入:js代码可以嵌入在网页head或body等任何地方,也可以放入单独的.js文件中然后通过<script src="">引入。
调试js:在浏览器开发者工具的console面板中可以直接编写js代码。
== ===:比较运算符相等和全等,==如果类型不同先转换类型,===如果类型不同这返回false。
NaN:是特殊的Number类型,与任何值的不相等,包括它本身。唯一判断NaN的方法时isNaN(NaN)//true。
strict模式:严格模式下必须使用var声明变量。在js代码的第一行写"use strict"来开启严格模式。
多行字符串:ES6新增了多行字符串的表示方式,使用``反引号。
模板字符串:ES6新增了模板字符串,`${varName}`。
string:字符串可以类似数组一样操作,获取长度,索引字符等。
数组:声明方式[1,2,obj]或new Array(1,2,obj)。
对象:js对象是一个无序的键值对组成的集合,键必须是字符串,值可以是任意类型。当键含有特殊字符时需使用''引号,访问时也要使用[“abc-abc”]。
检查对象是否拥有某一属性使用 in操作符 'name' in xiaoming; //true,如果这个属性是xiaoming原型链中的属性,也会返回true。检测自身属性时使用xiaoming.hasOwnProperty('name');。
Map和Set:Map和Set是ES6新引入的数据类型,Map是一组键值对数据结构,有极快的查找速度。Set只储Value,并且不能重复。
//声明map var map = new Map([['name', 'xiaoming'], ['age', 11]]); //或 var map2 = new Map(); map2.set('name', 'xiaoming');
//map2.delete('name'); console.log(map2.get('xiaoming'));
//声明set var set = new Set([1,2,'2']); //或 var set2 = new Set(); set2.add(1); set2.delete(2);
iterable:Array可以使用下标循环,但Map和Set就不行了,所以ES6标准引入了iterable类型,Array,Map,Set都是iterable类型,iterable类型可以使用for...of循环。
var a = [1,2,3]; var b = new Map(['a', 1], ['b', 2]); var c = new Set([1,2,3]); for(var item of c) { console.log(item[0] + ',' + item[1]); }
for in和for of:for in遍历的是对象的属性名称,for of仅遍历集合本身的元素。
forEach:iterable有forEach方法,接受一个回调函数,每次迭代都会调用回调函数。
var a = [1,2,3]; a.forEach(function(element, index, array) { //element是当前元素值 //当前索引 //数组本身 }); var s = new Set(['A', 'B', 'C']); s.forEach(function (element, sameElement, set) { console.log(element); }); var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]); m.forEach(function (value, key, map) { console.log(value); });
函数:声明函数function a(){}或使用var a = function(){}声明一个匿名函数并将匿名函数赋值给变量a。
rest参数:ES6中引入了rest参数 function a(x, y, ...rest){},xy以外的参数以数组的形式赋值给rest。如果参数不够,rest是一个空数组。
变量提升:js函数有一个特点是函数内部声明的变量都会提升到顶部,注意是声明提升,而赋值不会提升。未赋值的变量是undefined。
变量作用域:在函数内部声明的变量仅作用于函数内部。不在函数内部声明的变量具有全局作用域,相当于全局对象window的一个属性。
局部作用域:在for语句块中是无法定义具有局部作用域变量的,所以ES6引入了let,let可以声明一个块级作用域的变量。
常量:ES6引入了const关键字来定义常量,const和let一样具有块级作用域。
解构赋值:ES6引入了解构赋值,可以同时对一组变量进行赋值。
var list = [1,2,3]; var [x,y,z] = list;//分别给xyz赋值123. var person = { name: '小明', age: 20, gender: 'male', passport: 'G-12345678', school: 'No.4 middle school' }; var {name, age, passport} = person;
方法:在对象中绑定一个函数,称为这个对象的方法。
this:方法内部可以使用this关键字,指向调用方法的对象。如果不通过对象调用函数,在strict模式下this指向undefined,非strict模式下this指向window。方法内部的函数中的this指向window或undefined。
apply:可以使用函数的apply方法来控制this的指向,func.apply(obj, []);func函数中this指向obj。call()和apply()类似,唯一不同的是apply是把参数放到数组中再传入,而call可以直接接受多个参数。对于一般函数Math.max.call(null, 1,2,3); 第一个参数传入null即可。
高阶函数:一个函数接受另一个函数作为参数,称为高阶函数。
map/reduce:map是定义在Array中的高阶函数,可以传入自定义函数作为参数,从而返回一个新的数组。reduce接受的函数必须有两个参数,其效果相当于[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; arr.map(String); // ['1', '2', '3', '4', '5', '6', '7', '8', '9']
//对一个Array求和,就可以用reduce实现: var arr = [1, 3, 5, 7, 9]; arr.reduce(function (x, y) { return x + y; }); // 25
filter/sort:这两个也是定义在Array中的高阶函数,filter接收一个函数,依次作用于每个元素,然后根据返回的是true还是false决定是否保留元素。
// 保留偶数 var list = [1,2,3,4,5]; var arr = list.filter(function(x){ return x%2===0; }); // [2,4]
sort接收一个排序函数,并且直接对原数组进行修改。
//倒序排序,我们可以把大的数放前面: var arr = [10, 20, 1, 2]; arr.sort(function (x, y) { if (x < y) { return 1; } if (x > y) { return -1; } return 0; }); // [20, 10, 2, 1]
闭包:一个函数a()内部的函数b()引用了函数a()内部的局部变量,并且函数a()返回内部函数b(),返回的函数引用着函数a()的局部变量,这就形成了闭包。换句话说,闭包就是携带状态的函数,并且状态对外隐藏。
箭头函数:ES6新增了箭头函数 x=>x+x;,相当于匿名函数,但有个显著的区别就是this的指向,箭头函数内部的this是词法作用域,由上下文决定。
var obj = { birth: 1990, getAge: function () { var b = this.birth; // 1990 var fn = function () { return new Date().getFullYear() - this.birth; // this指向window或undefined }; return fn(); } }; var obj = { birth: 1990, getAge: function () { var b = this.birth; // 1990 var fn = () => new Date().getFullYear() - this.birth; // this指向obj对象 return fn(); } }; obj.getAge(); // 25 //由于this在箭头函数中已经按照词法作用域绑定了,所以,用call()或者 //apply()调用箭头函数时,无法对this进行绑定,即传入的第一个参数被 //忽略: var obj = { birth: 1990, getAge: function (year) { var b = this.birth; // 1990 var fn = (y) => y - this.birth; // this.birth仍是1990 return fn.call({birth:2000}, year); } }; obj.getAge(2015); // 25
typeof:typeof可以判断对象类型,返回类型的字符串
typeof 123; // 'number'
typeof NaN; // 'number'
typeof 'str'; // 'string'
typeof true; // 'boolean'
typeof undefined; // 'undefined'
typeof Math.abs; // 'function'
typeof null; // 'object'
typeof []; // 'object'
typeof {}; // 'object'
几条经验总结
-
不要使用
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'
。 - 数字转为字符串用
123..toString(); // '123', 注意是两个点! (123).toString(); // '123'
浏览器对象:js可以获取浏览器提供的很多对象,并对其操作。
window:window对象不但充当全局作用域,而且表示浏览器窗口。innerWidth和innerHeight表示浏览器内部宽高,是指去掉菜单栏、导航栏后用于显示网页的净宽高。
navigator:表示浏览器信息,有navigator.appName浏览器名称,navigator.appVersion浏览器版本等属性。
screen:表示屏幕信息,screen.width表示屏幕宽,单位是像素。
location:表示当前页面的URL信息,location.href;//http://www.baidu.com,加载一个新的页面用location.assign();。
document:表示当前页面,由于HTML在浏览器中是DOM形式表示为树形结构,document就是整个DOM树的根节点。
history:保存了浏览器的历史记录。