javascript注

1、浮点数:

  • e表示法(科学计数法-10的指数次幂): let floatNum = 3.12e2; //等于312
  • 浮点数的最高精度是17位小数。
  • 浮点数计算精度远不如整数,0.15加0.15的和是0.3,但是0.1加0.2的和不是0.3而是0.30000000000000004。
  • 因为浮点数的精度问题,所以比较两个浮点数是否相等只能判断差值是否小于某个阈值:Math.abs(a-b) < 0.00001;

2、数值:

  • 数值范围:-Infinity(Number.NEGATIVE_INFINITY)到Infinity(Number.POSITIVE_INFINITY)
  • NaN:非数值
  • isNaN:判断元素是不是不是数字,isNaN('10'); //false,(可以被转换为数值10) isNaN('true'); //false,(可以被转换为数值1)

3、数值转换:

  • Number()
    • Boolean值,true和false分别被转换为1和0
    • null值,返回0
    • undefined值,返回NaN
    • 数字值,返回数字
    • 字符值,包含数字会直接返回数字(忽略前导的0),包含十六进制格式会返回对应的十进制整数,空的会返回0,否则就返回NaN。
    • 对象,调用对象的valueOf()方法,然后依照前面的规则转换返回的值。如果转换的结果是NaN,则调用对象的toString()方法,然后再次依照前面的规则转换返回的字符串值。
  • parseInt()
    • 字符值,包含数字会直接返回数字
    • 0开头加数字的,ES3返回八进制对应的十进制数,ES5忽略前导的0,返回十进制数
    • 0x开头加数字的,返回十六进制对应的十进制数
  • parseFloat():始终都会忽略前导的0,只解析十进制数

4、字符串:

"I\'m ok!"; //如果字符串中含有引号可以用转义字符\
toUpperCase(); //把一个字符串变大写
toLowerCase(); //把一个字符串变小写
indexOf('ww'); //返回‘ww’在字符串里的索引位置
substring(2,5); //返回索引值在2-5之间的子串

5、数组:

var arr = [10, 20, 30, '30'];
arr.indexOf('30'); //搜索指定元素的索引值,返回3
arr.slice(1,2); //截取索引值1-2之间的array元素,返回[20, 30]
arr.push('A', 'B'); //向数组末尾添加若干元素
arr.pop(); //删除数组的最后一个元素
arr.unshift('B'); //向数组头部添加若干元素
arr.shift(); //删除数组的第一个元素
arr.sort(); //对数组进行排序,会直接修改当前数组的元素位置
arr.reverse(); //数组反转
arr.splice(2,3,'H','B'); //从索引2开始删除3个元素,再添加两个元素
arr.concat([1, 2]); //链接两个数组,返回新的数组
arr.join('-'); //数组遍历成字符串,并用指定的‘-’连接起来

6、对象

var jone = {
   name: 'Jone',
   birth: 1900,
   school: 'No.1 Middle School',
   height: 1.85,
age: function(){
var y = new Date().getFullYear() - this.birth; //this指向当前对象
return y;
} }; jone.height; //返回1.85 'name' in jone; //判断对象中是否有某个属性,返回true 'toString' in jone; //该属性是继承得到的,也返回true jone.hasOwnProperty('toString'); //判断属性是不是自身拥有的,返回false
jone.age();
function getAge(){
   var y = new Date().getFullYear() - this.birth;
    return y; 
}   
var jone = {
   name: 'Jone',
   birth: 1900,
   school: 'No.1 Middle School',
   height: 1.85,
 age: getAge
};
getAge.apply(jone, []); //jone调用getAge方法,参数为空
getAge.call(jone,); //jone调用getAge方法,参数为空

冻结对象jone:一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。

Object.freeze(jone);

7、Map(ES6,一组键值对)

var m = new Map([['Jone', 95], ['Bob', 80]]);
m.get('Bob'); //返回80
m.set('Adam', 88); //添加新的key-value
m.delete('Bob'); //删除key‘Bob’

8、Set(ES6,一组key的集合,没有重复的key)

var s1 = new Set(); //空set
var s2 = new Set([1, 2, 3]);
s2.add(4); //为set添加key‘4’
s2.delete(3); //为set删除key‘3’

9、iterable(ES6)

for ... in循环出来的是属性名,for...of完全修复了这些问题

var a = ['A', 'C', 'D'];
var s = new Set(['A', 'B']); var m = new Map([[1, 'x'], [2, 'y']]);
for(let x of a){ //遍历
console.log(x);
} for(let x of s){ //遍历 console.log(x); } for(let x of m){ //遍历 console.log(x[0] + '=' + x[1]); }

forEach是ES5.1标准引入的

//Set没有索引,因此前两个参数都是元素本身,参数可省略
var s = new Set(['1', '2']);
s.forEach(function(element, sameElement, set){
    console.log(element);
});
//Map的参数依次为value、key、map本身
var m = new Map([['A', '1'], ['B', '2']]);
m.forEach(function(value, key, map){
    console.log(key + '=' + value);
});

10、函数

函数体内部的语句在执行时,一旦执行到return时,函数就执行完毕,并将结果返回。注意return语句一定不要换行。

function abs(a,b){
  console.log(arguments.length); //返回函数参数的个数,返回2  
}

...rest参数(ES6):用于返回除了前面参数外的所有参数,只能写在最后

function foo(a, b, ...rest){
  console.log(rest);
}
foo(1,2,3,4,5); //返回[3, 4, 5]

11、变量作用域:全局变量和局部变量

  • var声明的变量会向上提升
  • ES6新的const和let变量都具有块级作用域
  • 变量解构:let[x, y, z] = [1, 2, 3];

12、高阶函数

map():按照原始数组元素顺序一次处理元素,不会改变原始数组(参数:当前元素的值,当前元素的索引值,当前元素属于的数组对象)

function pow(x){
  return x*x;  
}
var arr = [1, 2, 3, 4];
var result = arr.map(pow); //result:[1, 4, 9, 16]

reduce():函数累加器,从左往右计算(参数:初始值,或者计算结束后的返回值,当前元素,当前元素的索引值,当前元素属于的数组对象)

var arr = [1, 3, 5, 7, 9];
arr.reduce(function(x,y){
    return x*10+y;
}); //13579

filter():根据特定条件过滤数组(参数:当前元素的值,当前元素的索引值,当前元素属于的数组对象)

var arr = [1, 2, 4, 6, 7];
var r = arr.filter(function(x){
    return x%2 === 0;
}); //[2, 4, 6]
//利用filter去除重复元素
var arr = ['app', 'saa', 'apple', 'app', 'des', 'apple'];
var r = arr.filter(function(ele, index, self){
    return self.indexOf(ele) === index;
});

sort():按照指定规则为数组排序

//数字从小到大排序
var arr = [1, 50, 10, 2];
var r = arr.sort(function(x,y){
    if(x<y){
      return -1;     
    }else if(x>y){
      return 1;  
    }else{
      return 0;  
    }
});
//字母升序排列
var r = arr.sort(function(x1,y1){
    x2 = x1.toUpperCase();
    y2 = y1.toUpperCase();
    if(x2<y2){
        return -1;
    }else if(x2>y2){
        return 1;
    }else{
        return 0;
    }
});

数组every():检测所有元素是否符合条件,如果都符合就返回true,否则返回false(参数:当前元素的值,当前元素的索引值,当前元素属于的数组对象)

//判断是否所有元素是不是小写
var arr = ['app', 'add', 'brand', 'bed'];
var r = arr.every(function(x){
    return x.toLowerCase() === x;
});

数组find():查找符合条件的第一个元素(参数:当前元素的值,当前元素的索引值,当前元素属于的数组对象)

数组findIndex():查找符合条件的第一个元素的索引(参数:当前元素的值,当前元素的索引值,当前元素属于的数组对象)

generator(生成器,ES6):generator可以在执行过程中多次返回

try {
    r1 = yield ajax('http://url-1', data1);
    r2 = yield ajax('http://url-2', data2);
    r3 = yield ajax('http://url-3', data3);
    success(r3);
}
catch (err) {
    handle(err);
}

13、Date对象

var d = new Date();
d; //Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
d.getFullYear(); //2015
d.getMonth(); //5
d.getDate(); //24
d.getDay(); //3
d.getHours(); //19
d.getMinutes(); //49
d.getSeconds(); //22
d.getMillideconds(); //675
d.getTime(); //1435146562875

14、RegExp正则表达式

\d匹配一个数字;\w匹配一个字母或数字;\s匹配一个空格;.匹配任意字符;*表示任意字符;+表示至少一个字符;?表示0或1个字符;{n}表示n个字符;{n,m}表示n-m个字符。

\d{3,8};  //匹配3-8个数字

要做更精确的匹配,可以用[]表示范围。^表示行的开头;$表示行的结尾。

^\d; //表示必须以数字开头
\d$; //表示必须以数字结尾
[0-9a-zA-Z\_]+; //表示至少由一个数字、字母或者下划线组成的字符串

js有两种正则表达式,一种是通过/正则表达式/写出来,第二种是通过new RegExp('正则表达式')创建出来。

var r1 = /^\d{3,8}\-\d{1,2}$/;
var r2 new RegExp('^\d{3,8}\-\d{1,2}$');

正则表达式分组,()表示要提取的分组。

var r1 = /^(\d{3})-(\d{3,8})$/;
r1.exec('010-123456'); //['010-123456', '010', '123456']

全局匹配g:当我们指定g标志后,每次运行exec(),正则表达式本身会更新lastIndex属性,表示上次匹配到的最后索引(不能使用/^...$/

var s = 'JavaScript, VBScript, JScript and ECMAScript';
var re=/[a-zA-Z]+Script/g;

// 使用全局匹配:
re.exec(s); // ['JavaScript']
re.lastIndex; // 10

re.exec(s); // ['VBScript']
re.lastIndex; // 20

re.exec(s); // ['JScript']
re.lastIndex; // 29

re.exec(s); // ['ECMAScript']
re.lastIndex; // 44

re.exec(s); // null,直到结束仍没有匹配到

15、面向对象编程

构造函数:

//每个对象都共享hello函数,减少内存
function Student(name){
  this.name = name;  
}
Student.prototype.hello = function(){
  alert('Hello,' + this.name + '!');
}
let l1 = new Student('Joe');
let l2 = new Student('Kitty');
l1.hello === l2.hello; //true
//不推荐,浪费内存
function Student(name){
  this.name = name;
  this.hello = function(){
    alert('Hello,' + this.name + '!');
  }
}
let l1 = new Student('Joe');
let l2 = new Student('Kitty');
l1.hello === l2.hello; //false

class:

class student {
  constructor(name){
    this.name = name;
  }
}
//class继承
class Cat extends Student {
  constructor(name){
    super(name); //用super调用父类的构造方法
} say() { return 'Hello,' + this.name + '!'; } }

16、DOM

更新DOM:innerHTML和textContent

p.innerHTML = '<p>new</p>'; //html代码
P.textContent = 'new'; //纯文字

插入DOM:appendChild和insertBefore

<!-- HTML结构 -->
<div >
    <p >Java</p>
    <p >Python</p>
    <p >Scheme</p>
</div>

//appendChild
var list = document.getElementById('list');
var js = document.createElement('p');
list.appendChild(js);
//insertBefore
var java = document.getElementById('java ');
liat.insertBefore(js, java);

删除DOM:removeChild

liat.removeChild(java);

classList:

//contains判断是否包含样式
document.getElementById('a').classList.contains('active');
//add新增样式
document.getElementById('a').classList.add('active');
//remove移除样式
document.getElementById('a').classList.remove('active');
//toggle不管类名是否存在,true强制添加类,false强制移除类
document.getElementById('a').classList.toggle('active', true);
document.getElementById('a').classList.toggle('active', false);
//item返回索引值为0的类名
document.getElementById('a').classList.item(0);
//length返回类的个数
document.getElementById('a').classList.length;

17、表单提交

出于安全考虑,提交表单时不传输明文口令,而是MD5

var pwd = document.getElementById('password');
var md5pwd = document.getElementById('md5-password');
md5pwd.value = toMD5(pwd.value);
return true;

18、上传文件控件

let f = document.getElementById('text-file-upload');
let filename = f.value;
//判断文件格式
if(!filename || !(filename.endsWith('.jpg') || filename.endsWith('.png') || filename.endsWith('.gif'))){
    alert('请上传正确的文件格式!');
    return false;
}

上传图片并预览

<div >
    <img src="" alt="img" width="400" >
</div>
<input >
<script>
    let f = document.getElementById('image-upload');
    let s = document.getElementById('image-preview').querySelector('img');
    f.addEventListener('change',function(){
        if(!(f.value)){
            alert('没有选择文件');
            return false;
        }
        //获取file信息
        let file = f.files[0];
        if(file.type !== 'image/jpeg' && file.type !== 'image/jpg' &&file.type !== 'image/gif' &&file.type !== 'image/png'){
            alert('不是有效的图片文件');
            return false;
        } //限制图片格式
        if(file.size/1024>2048){
            alert('上传图片大小不要超过2M');
            return false;
        } //限制图片大小
        //读取文件
        let reader = new FileReader();
        reader.onload = function(e){
            s.src = e.target.result;
            s.style.display = 'block';
        };
        //以DataURL的形式读取文件
        reader.readAsDataURL(file);
    });
</script>

19、JSON

JSON.stringify(obj); //对象转换为json串

20、

21、

offsetWidth水平方向 width + 左右padding + 左右border-width
offsetHeight垂直方向 height + 上下padding + 上下border-width
clientWidth水平方向 width + 左右padding
clientHeight垂直方向 height + 上下padding
offsetTop获取当前元素到 定位父节点 的top方向的距离
offsetLeft获取当前元素到 定位父节点 的left方向的距离
scrollWidth元素内容真实的宽度,内容不超出盒子高度时为盒子的clientWidth
scrollHeight元素内容真实的高度,内容不超出盒子高度时为盒子的clientHeight
innerWidth浏览器窗口可视区宽度(不包括浏览器控制台、菜单栏、工具栏)
innerHeight浏览器窗口可视区高度(不包括浏览器控制台、菜单栏、工具栏)