ECMA-262 的第 5 版是 JS 的第一个稳定版本,获得了各浏览器厂商的支持。
javascript
文档对象模型是针对 XML 但通过扩展用于 HTML 的 API 。DOM 把整个页面映射为一个多层次节点结构。HTML 或 XML 页面中的每一个组成部分都是某种类型的节点,这些节点又包含着不一样类型的数据。
document object model 文档对象模型,里面提供了一些属性和方法,可让咱们操做页面的元素css
原则上讲,BOM只处理浏览器窗口和框架,但下面一些针对浏览器的 JS 扩展也被看作是BOM的一部分。
browser object model 浏览器对象模型,里面提供了一些属性和方法,可让咱们操做浏览器。html
<div onclick="alert('hello world')"></div>
复制代码
<script> alert('hello world') </script>
复制代码
// 新建一个js文件
<script src="./js/demo.js"></script>
// or
<script src="./js/demo.js" type="text/javascript"></script>
复制代码
内嵌导入和外链导入不能合并在一块儿,若是当前是外链导入的,那么在script脚本块找那个编写的全部代码都不会被执行。java
<script src="./js/demo.js">
alert('hello world')
</script>
复制代码
咱们通常性会把css放在body的上面,把js放在body末尾(约定速成的规范)node
可是若是放在了标签前面那么将如何处理?面试
页面加载完全部资源以后执行操做编程
在js中json
window.onload=function(){
}
复制代码
在jq中后端
$(document).ready(function(){
})
window.addEventListener('load',function(){},false);
// ie8如下
window.attachEvent('onreadystatechange',function(){
})
复制代码
alert(1)
alert({name:'wjw'}) //=> '[object Object]'
alert([13,14]) //=> '12,13'
复制代码
var wjw = confirm("are you sure");
alert(wjw);
复制代码
var flag = prompt("are you sure");
alert(flag)
复制代码
控制台输出,方便开发调试数组
console.log({name:'wjw'});
console.dir() //比log输出更加详细一些
console.table //把json数据展现成一个表格
复制代码
语法 ECMAScript 的语法大量借鉴了 C 及其余类 C 语言(如 Perl 和 Java)的语法。 区分大小写
// 单行注释
/* * 这是一个多行 * (块级)注释 */
复制代码
严格模式 ES5 引入了严格模式的概念,在严格模式下,ES3 中的一些不肯定行为将获得处理,并且队某些不安全的操做也会抛出错误。要在整个脚本中启用严格模式,能够在顶部添加以下代码:
这行代码看起来像是字符串,并且也没有赋值给任何变量,但其实它是一个编译指 示(pragma),用于告诉支持的JavaScript引擎切换到严格模式。在函数内部的上方包含这条编译指示,也能够指定函数在严格模式下执行:
function doSomething(){
"use strict"; //函数体
}
复制代码
变量是能够变得 常量是不可变的
js定义变量的方法
// var 变量名 = 值;
var num = 12;
var name = 'wjw'
复制代码
const num = 12;
复制代码
var test = 'wjw';
var Test = 'wjh';
console.log(test);
// 输出test
复制代码
第一个单词首字母小写,其他每个有意义单词首字母大写
var studentInfo; // 学生信息
// 所见即所得
// 例子:
/* * info : information 信息 * init : initlization 初始化 * add/insert/create 增长插入建立 * remove/rm/clear/del/delete 删除 * update 修改 * get/query/select : 查询获取 */
复制代码
var student_info;
var $xxx; //=> 通常都是应用jq得到到的值
var _xxx; //=> 通常这样的状况表明变量是一个局或者公共的变量
复制代码
操做符 typeof 是用来检测给定变量的数据类型的操做符。对一个值使用 typeof 操做符可能返回下列某个字符串:
"undefined"
"boolean"
"string"
"number"
"object" // 若是这个值是对象或者null "function"
复制代码
Boolean()
叹号在JS中海油一个做用:取反,先把值转换为布尔类型,而后再去取反
!!
在叹号取反的基础上取反,取反两次至关于没有操做,可是却已经其余类型值转化为布尔类型了,和Boolean是相同的效果
在JS中单引号和双引号包起来的都是字符串
12 - > number
'12' -> string
'[12,23]' -> string
复制代码
第一种是使用几乎每一个值都有的 toString()方法。多数状况下,调用 toString() 方法没必要传递参数,但在调用数值的 toString()方法时,能够传递一个参数:输出数值的基数。默认状况下,toString() 方法以十进制格式返回数值的字符串表示。而经过传递基数,toString() 能够输出二进制、八进制、十六进制等。
var num = 10;
alert(num.toString()); // "10"
alert(num.toString(2)); // "1010"
alert(num.toString(8)); // "12"
alert(num.toString(10)); // "10"
alert(num.toString(16)); // "A"
复制代码
经常使用方法
0 12-22 12.5 js中多增长了一个number类型的数据NaN typeof NaN -> Number
var intNum = 55; // 十进制整数 var octalNum1 = 070; // 八进制的56
var octalNum1 = 079; // 无效的八进制数值——解析为79
var octalNum1 = 08; // 无效的八进制数值——解析为8
var hexNum1 = 0xA; // 十六进制的10
var hexNum2 = 0x1F; // 十六进制的31
复制代码
注意,八进制字面量在严格模式下是无效的,会致使抛出错误。
ECMAScript 可以表示的最小数值保存在 Number.MIN_VALUE 中——在多数浏览器中,这个值是 5e-324;可以 Number.MAX_VALUE 中——在大多数浏览器中,这个值是1.7976931348623157e+308。若是某次计算的结果获得了一个超过JavaScript 数值范围的值,那么这个数值将会自动转换为 Infinity 值,若是这个数值是负数,则会转换成 -Infinity(负无穷),若是这个数值是正数,则会转换成Infinity(正无穷)。要肯定一个数值是否是有穷的,可使用 isFinite() 函数。
isNaN(0) // ->false
isNaN(NaN) // ->true
复制代码
isNaN('12') //->false
复制代码
Number('12') // -> 12
Number('12px') // ->NaN
// 在使用Number转换的时候只要字符串中出现任何一个非有效数字字符,最后的结果都是NaN
Number(true) //-> 1
Number(false) //-> 0
Number(null) // -> 0
Number(undefined) //->NaN
复制代码
Number([]) // -> ""
Number([12]) // -> 12
Number([12,13]) // -> 12,13 (,是非有效字符) -> NaN
Number({age:12}) // ->NaN
Number({}) // -> NaN
复制代码
Number('12px') // -> NaN
parseInt('12px') // -> 12
复制代码
parseInt('12px13') // -> 12
复制代码
处理整数最经常使用的仍是 parseInt() ,它会忽略字符前面的空格,直到找到第一个非空格字符。若是第一个字符不是数字字符或者负号,parseInt() 就会返回 NaN;也就是说,用 parseInt() 转换空字符串会返回 NaN 。若是第一个字符是数字字符, parseInt() 会继续解析第二个字符,直到解析完全部后续字符或者遇到了一个非数字字符。若是字符以“0x”开头且后面跟数字字符,会被解析为 16 进制整数;
以“0”开头且后面跟数字字符,会被解析为 8 进制整数。下面给出一些例子:
var num1 = parseInt("1234blue"); // 1234
var num2 = parseInt(""); // NaN
var num3 = parseInt("0xA"); // 10(十六进制)
var num4 = parseInt(22.5); // 22
var num5 = parseInt("70"); // 70
var num6 = parseInt("0xf"); // 15(十六进制)
复制代码
pareInt('12.5px') -> 12
pareFloat('12.5px') -> 12.5
复制代码
ECMAScript 中的对象其实就是一组数据和功能的集合。对象能够经过执行 new 操做符后跟要建立的对象类型的名称来建立。而建立 Object 类型的实例并为其添加属性和(或)方法,就能够建立自定义对象,以下所示:
var o = new Object();
复制代码
每个对象都是由零到多组 属性名(key键):属性值(value值) 组成的,或者说有多组键值对组成的,每一组键值对中间用逗号分隔
描述这个对象特色特征的
var obj ={name:'wjw',age:8};
复制代码
某个属性名对应的属性值或者数字格式的
obj.name
obj['name']
复制代码
属性值能够是任何数据类型
// 若是属性名是数字如何操做
obj.0 语法不支持
obj[0] / obj['0'] 两种都支持
复制代码
若是操做的属性名在对象中不存在,获取的结果是undefined
obj.sex // ->undefined
复制代码
一个对象的属性名是不能重复的(惟一性),若是以前存在就是修改属性值的操做,反之不存在就是新的设置属性的操做
obj.sex = '男';
obj['age'] = 9;
复制代码
obj.sex = null;
复制代码
delete obj.sex
复制代码
JS是运行在浏览器中的(内核引擎),浏览器会为JS提供赖以生存的环境(提供给js代码执行的环境)=> 全局做用域window(global)
var a = 12;
var b = a; // 把A变量存储的值赋值给B
b = 13;
console.log(a);
var n ={name:'wjh'};
var m = n;
m.name = 'wjw'
console.log(n.name)
复制代码
函数数据类型也要按照引用地址来操做的
函数:具有必定功能的方法
// => 建立函数:
function 函数名(){
//=> 函数体:实现某一个功能的具体JS代码
}
// => 执行函数:至关于使用洗衣机洗衣服(若是函数只建立了,可是没有去执行,函数没有任何的意义)
// 函数名()
复制代码
function fn(){
console.log(1+1);
}
fn; // => 输出函数自己
fn(); // => 把函数执行(吧函数体重实现功能的代码执行)
复制代码
形参:形式参数(变量),函数的入口
当咱们建立一个函数想要实现个功能的时候,发现有一些材料不清楚,只有当函数运行的时候,别人传递给我,我才知道,此时咱们就须要设定入口,让用户执行的时候经过入口把值把咱们
function fn(num1,num2){
console.log(num1+num2)
}
// 实参:函数执行传递给函数的具体值就是实参
fn(1,2);
fn(10,20);
复制代码
把其余数据类型转换为number类型
-> isNaN、Number、pareInt、parseFloat
-> 在进行数据加减乘除数学运算的时候
// true -> 1 false->0
// ''->0 '12'->12 '12px'->NaN/12
// '小伙子'->NaN
// null -> 0
// undefined-> NaN
{} /^$/ function() ->NaN
[]
[12]->'12'->12
['12,13']->'12,23'->NaN
// => 引用数据类型转换为数字
// 经过toString方法把数组转换为字符串,而后在调用Number转换为数字
复制代码
1-'1' -> 0
10*null -> 0
10/undefined -> NaN
10*[10]->100
复制代码
1+'1' -> '11'
null+'1' -> ‘null1’
复制代码
[] -> true
-1 -> true
if(box){
// => 首先把box变量存储的值获取到,转化为布尔类型,若是为true条件成立,反之不成立
}
if(3+'3px'){
// 条件成立: 3 + '3px' = '33px'
}
if(3-'3px'){
// 条件不成立: 3-'3px' = NaN
}
复制代码
在使用==进行比较的时候,若是左右两边的数据不相同,浏览器默认转换为相同的类型,而后在比较('==='不会这样操做)
// 对象和对象: 应用数据类型比较的空间地址不同,不是一个空间
[] == [] -> false
var a ={}
var b = a;
a==b -> true
复制代码
[]== 0 -> true
({})=== NaN -> false
NaN和本身不相等和其它任何值都不相等
复制代码
[]==='' -> true
复制代码
[]==true -> 0==1 ->false
[]==false -> 0==0 ->true
![]==false -> ![] ->把数组变成为布尔在取反=false
false=false -> true
复制代码
字符串和数字:字符串转换为数字
字符串和布尔:都转为数字
布尔和数字:布尔转换为数字
规律:两个等于号比较,左右两边数字值的类型不同,浏览器会吧两边的类型都转换为数字而后再比较,可是null和undefined除外
null==undefined -> true
null===undefined -> false
null 和 undefined 和其它任何都不相等
null==0 -> false null以及undefined和其它任何值都不相等
判断操做语句
if(条件1){
//=>条件1成立执行的操做
}else if(条件2){
//=>上面条件不成立,条件2成立,执行的操做
}
...
else{
// => 以上条件都不成立执行的操做
}
复制代码
若是好几个条件都成立了,只吧第一个成立的条件执行,后面成立的条件忽略无论
条件:
A==B、A!=B、A>B、A<B
if(A){} // 先把A转换为布尔类型,判断真假以此来决定是否成立
//否成立
if(A>B&&A<10){} //只有两个小条件都是真,总体条件为真
if(A>B||A<10){} // 只要其中一个小条件成立,总体条件是真
复制代码
BAT 面试题
var num = parseFloat('width:12.5px');
if(num==12.5){ // =>NaN
alert(12.5);
}else if(num==NaN){ // NaN!=NaN
alert(NaN);
}else if(typeof num=='number'){ //
alert(0)
}else{
alert("啥也不是")
}
复制代码
条件?条件成立执行:条件不成立执行
if(条件){}else : 三元运算符就是这种简单if..else..的另外一种写法
var num = 10;
if(num>5&&num<10){
num++;//累加1
}else{
num--;
}
// 修改为为三元运算符,若是条件成立或者不成立的某一种状况并不须要什么处理
// 咱们空着语法不符合,咱们使用null、undefined、void 0(就是undefined)占位就能够
num>5&&num<10?num++:num--;
复制代码
var num = 10;
if(num>5 && num<10){
num++;
break;/continue;/return;
}
// => 修改为为三元运算符
// 在三元运算符的操做中不能出现break、continue、return这样的关键词,因此咱们没法用三目代替if、else
num>5 && num<10?
(num++,return):null;
复制代码
swith case应用于if、else中一个变量在不一样值状况下的不一样操做
var num =10;
switch(num){
//switch后面小括号中存放的是一个值(通常咱们都写变量;把变量存储的值拿来用,有时候也多是一个计算)
case 1:
// case后面放的都是值,目的验证switch后面的值和哪种case后面的值相等,相等的进行对应的处理
...
break;
// 每一种case借宿后都要加break借宿当前的判断
case 10:
...
break;
default:
// switch后面的值和每一种case状况对应的值都不相等,执行最后的default,相似于false
...
}
复制代码
案例分析
var num = 5;
switch(num%2){//=>先把取余操做进行运算,拿运算结果case比较
case 0:
num++;
break; //不加break,无论后面的条件是够成立,都会继续向下执行,知道遇到break为止
// 不加break,就能够实现||这样的操做
case: 2-1: //case后面也应该是值,此处先把2-1计算,把计算的结果和switch值比较
num--;
// 最后一项能够不加break,不加也能跳出判断
break;
}
num%2:让num存储的值除以2去余数(0或者1)
复制代码
swich case 中的比较实用的"==="
循环,重复作一件事情
for(设置循环起始值;设置循环执行的条件;步长累加){
// 循环体:重复作的事情都是在循环体重
}
复制代码
for(;i<5;;){
consloe.log(i);
//没有步长累加,咱们的i永远是0,循环条件永远成立“死循环”;
//项目中不能出现死循环,一旦出现,循环下面的事情都作不了
}
复制代码
结束本轮循环,继续执行下一轮:循环体重continue后面的代码都不会在执行,它会直接的去执行步长,而后进行下一轮
for(var i=0;i<5;i+=2){
console.log(i)
continue;
}
复制代码
结束整个循环:循环体重一旦遇到break首前后面代码不执行了,并且步长累加也不执行了,循环都结束了
for(var i=0;i<5;i+=2){
console.log(i)
break;
}
复制代码
BAT面试题
for(var i=1;i<10;i+=2){
if(i<5){
i++;
continue;
}else{
i+=3;
break;
}
console.log(i)
}
console.log(i) // =>10
复制代码
用来遍历(循环)对象键值对的
var obj = {name:wjw,age:8,0:'wjh',3:'ylp',1:'cx'}
for(var key in obj){
console.log('ok')
// key 属性名 string
console.log(obj.key)
//获取obj中key这个属性对应的值 ->undefined <=> obj['key']
console.log(obj[key]);
//->每一次循环把key变脸存储的值(当前遍历的属性名)获取到放在中括号中,获取obj对应的属性值
}
for(var key in obj){
if(obj.hasOwnProperty(key)){
}
}
复制代码
DOM:document object model 文档对象模型,提供一些属性和方法可让咱们去操做DOM元素
node 节点,浏览器默认在一个html页面中的全部内容都是节点(包括标签、注解、文字文本等)
元素节点
[curEle].tagName:获取当前元素的标签名(获取的标签名通常都是大写)
文本节点
nodeType:3
nodeName:#text
nodeValue:文本内容
注释节点
nodeType:8
nodeName:#comment
nodeValue:注释内容
文档节点
nodeType:9
nodeName:#document
nodeValue:null
<-- div#box>(ul>li{0$}*3)+div{内容$}*3-->
<div id="box">
<ul>
<li>01</li>
<li>02</li>
<li>03</li>
</ul>
<div>内容1</div>
<div>内容2</div>
<div>内容3</div>
</div>
复制代码
<div id="box1"></div><div id="box2"></div><div id="box1"></div>
<script>
console.log(box1) // -> [div#box1, div#box1, box1: div#box1]
</script>
复制代码
<input id="myInput" type="text" size="20"/><br />
<script> var x=document.getElementsByName("myInput"); </script>
复制代码
<input name="myInput" type="text" size="20"/><br /> <script> var x=document.getElementsByName("input"); </script> var bodyBox = document.getElementsByTagName('body'); bodyBox[0].getElementsByTagName('div'); 复制代码
<input name="myInput" type="text" size="20"/><br />
<script> var x=document.getElementsByName("input"); </script>
复制代码
经过元素的NAME属性值获取一组元素(类数组:节点集合NodeList) 他的上下文只能是document
<input name="myInput" type="text" size="20"/><br />
<script> var x=document.getElementsByName("myInput"); </script>
复制代码
document.documentElement.clientWidth||document.body.clientWidth
// 获取当前浏览器可视区域的宽度(当前页面一个屏幕的宽度)
// =>clientHieght 获取高度
复制代码
querySelector 获取一个元素对象
querySelectorAll 获取的一个元素集合
只要css支持的选择器,这里大部分都支持
document.querySelector('#box1');
document.querySelectorAll('.box1');
document.querySelectorAll('div');
document.querySelectorAll('body>div');
document.querySelectorAll('#box1 li');
复制代码
节点是用来描述页面中每一部门之间关系的,只要我能够获取页面中的一个页面,那么我就能够经过相关的属性和方法获取页面中全部的节点
获取当前元素全部的子节点(节点集合:类数组) 注:不只仅是元素子节点,文本、注释等都会包含在内:子节点说明只是在儿子辈分中查找
获取全部的元素子节点(元素集合) 在IE6-8下获取的结果和标准浏览器中有区别(IE6-8中会把注释点当作元素节点获取到)
获取当前元素的父节点(元素对象)
获取当前节点的上一个各个节点上一个哥哥节点(不必定是元素节点也多是文本或者注释)
获取当前节点的下一个弟弟节点
获取当前节点的上一个哥哥元素节点
获取当前节点下一个弟弟元素节点 IE6-8不兼容
当前元素全部子节点中的第一个(也不必定是元素节点,多是文本和注释)
当前元素多有子节点中的最后一个 fistElementChild lastElementChild(IE6-8兼容)
真实项目中,咱们偶尔会在js中动态建立html标签,而后把其增长到页面中
在js中动态建立一个html标签
容器.appendChild(新元素) 把当前建立的新元素添加到容器的末尾位置
容器.inserBefore(新元素、老元素) 在当前容器中,把新建立的元素增长到老元素以前
// 建立
var oDiv = document.createElement('div');
oDiv.id='div1';
oDiv.className = 'box';
// 添加到页面中
document.body.appendChild(oDiv);
document.body.inserBefore(oDiv,box2);
复制代码
var link = document.createElement('a');
link.href = 'http://www.baidu.com?name=1&age=2#haha'
consloe.dir(link);
// hash:存储饿哈希值 '#haha'
// hostname:域名 'www.baidu.com'
// pathname:路径 '/stu/'
// protocol:协议 'http:'
// search:问号传递参数值 '?nname=1&age=2'
复制代码
真实项目中不少须要经过动态建立元素来完成的,其中有一个需求:解析一个url地址每一部分的信息(包括问号传值的参数值)
function queryURLParameter(url){
var link = document.createElement('a');
link.href=url;
var search = link.search,
obj = {}'
if(search.length===0) return;
search = search.substr(1).split(/&|=/g);
for(var i=0;i<search.length;i+=2){
var key = search[i],
value = search[i+1];
obj[key]=value;
}
link = null;
return obj;
}
复制代码
给当前元素设置/获取/移出属性的(通常操做的都是它的自定义属性)
box.setAttribute('myIndex',0)
box.getAttribute('myIndex')
box.removeAttribute('myIndex')
复制代码
使用xxx.index=0 和xxx.setAttribute('index',0)这两种设置自定义属性的区别
xxx.index : 是吧当前操做的元素当作一个普通对象,为其设置一个属性名
xxx.setAttribute:把元素当作特殊的元素对象来处理,设置的自定义属性是和页面结构中的DOM元素映射在一块儿的
JS中获取的元素对象,咱们能够把他理解为两种角色:
元素对象中的内置属性,大部分都和页面的标签存在映射关系:
xxx.style.backgroundColor = 'xxx' 此时不只把js中对象对应的属性值改变了,并且也会映射到页面的html标签上(标签中有一个style行内样式,元素的样式改变了)
xxx.className = 'xxx'此时不只是吧js对象中的属性值改变了,并且页面中的标签增长了class样式类(能够看见的)
元素对象中的自定义属性: xxx.index=0
仅仅是吧js对象中增长了一个属性名(自定义的),和页面中的html没啥关系(在结构上看不见)
xxx.setAttribute:经过这种方式设置的自定义属性和以前提到的内置属性差很少,都是和html结构存在映射关系的(设置的自定属性能够呈如今结构上)
把当前页面中全部id叫作box1的都获取到
var allList = document.getElementsByTagName(*);
var result = []
for(var i=0;i<allList.length;i++){
var item = allList[i];
item.id === 'box1'?result.push(item)
}
console.log(result)
复制代码
获取当前元素的上一个哥哥元素节点(兼容全部的浏览器) curEle:current element
// 首先获取当前元素的上一个哥哥节点,判断当前获取的节点是否为元素节点(nodeType===1)
// 若是不是基于当前获取的节点,找他的上一个哥哥节点..(找几回不知道)一直到找到的节点是元素节点为止
// 若是在查找过程当中,发现没有上一个哥哥节点,找到头了,则再也不继续查找
function prev(curEle){
var p = curEle.previousSibling; // 属性返回同一树层级中指定节点的前一个节点。
while(p&&p.nodeType!==1){ //p:p!=null
p = p.previousSibling;
}
return p;
}
// 扩展
// next: 获取下一个弟弟元素节点
// prevAll:获取全部的哥哥元素节点
// nextAll:获取全部的弟弟元素节点
// siblings:获取全部的兄弟元素节点
// index:获取当前元素的兄弟中排名索引
复制代码
可是他是对象数据类型的
abs
Math.abs 取绝对值
cell / floor
cell: 向上取整 floor: 向下取整
round
round: 四舍五入
random
random: 获取一个[0,1]之间的一个随机小数
max/minx
max 获取一组值中的最大值 minx 获取一组值中的最小值
PI
Math.PI 获取圆周率
pow / sqrt
pow 获取一个值的多少幂 sqrt 获取一个值的开平方
在js中用单(双)引号包裹起来的都是字符串
var str = 'welcome to credan!'
复制代码
字符串就是由零到多个字符串组成的
第一个字符索引0
第二个字符索引1
...
有length的属性,存储的是当前字符串中字符的个数(字符串的长度)
以数字做为索引,从零开始的
str[0] -> 'w' 第一个字符
strlength-> 46
str[str.length-1] -> '!' 最后一个字符
str[100] -> undefined 若是指定的索引不存在获取的结果是undefined
真实项目中,咱们常常操做字符串,此时咱们须要掌握经常使用的一些字符床操做方法
console.dir(String.prototype)
charAt && charCodeAt
在charAt 基础上,把获取的字符变为Unicode编码值(对应ASCll码表)
String.fromCharCode(十进制的Unicode值),把值按照ascll码表中的信息,转为原有字符,charCodeAt正好对应
当索引是负数的时候,浏览器在处理的时候,是用字符串的总长度加上负数索引,而后按照正数处理操做
细节:
indexOf && lastIndexOf
若是当前字符在字符串中没有出现过,结果是-1:咱们根据这个规律可言验证一下当前字符串中是否包含某个字符
if(str.indexOf('?')===-1){
// => 没有出现过
}
if(str.indexOf('?')>=-1){
// => 出现过
}
复制代码
str.split 按照某个字符串分红数组中的某一项,和数组中的join方法是对应
str.replace 实现字符的替换 执行一次replace 只能替换一次,若是有好几个都须要替换,在不适用正则的状况下,咱们须要执行不少次replace
有些需求及时执行不少次repalce也实现不了,此时须要使用正则处理,真实项目中replace通常都是和正则搭配使用的
获取地址栏的值
function queryURLPrameter(url){
// => url 传递的参数
var quesIndex = url.indexOf('?'),
obj = {}
if(quesIndex === -1){ // url中没有问号传参 直接返回空
retrun obj;
}
url = url.substr(quesIndex + 1);
var ary = url.split('&');
for(var i =0;i<ary.length;i++){
var curAry = ary[i].split('=');
obj[curAry[0]] = curAry[i];
}
return obj
}
复制代码
String.prototype.myQueryURLParameter = function myQueryURLParamter(){
var obj = /([^=?&]+)=([^=?&]+)/g;
this.replace(reg,function(){
var arg = argments;
obj[arg[1]] = arg[2]
})
return obj;
}
var str = 'https://www/baidu.com/s?wd=1233213&issp=1';
console.log(str.myQueryURLParameter());
复制代码
经过它能够对时间进行处理
var time = new Date();
// 获取当前客户端本机时间(当前获取的时间不能做为重要的参考依据)
// 获取结果是一个日期格式的对象
// Wed Mar 20 2019 17:37:16 GMT+0800 (中国标准时间)
typeof new Date() -> object
time.getFullYear() 获取四位数全年
time.getMonth() 获取月份
time.getDate() 获取日
time.getDay() 获取星期(0-6表明周日-周六)
time.getHours() 获取小时
time.getMinutes() 获取分钟
time.getSeconds() 获取秒
time.getMilliseconds() 获取毫秒
time.getTime() 获取当前日期距离'1970-01-01 00:00:00'的毫秒差
复制代码
var time = new Date('2017-10-22');
// 当new Date 中传递一个时间格式的字符串,至关于把这个字符串换位标准时间对象
// (转换完成后,就能够调取上面咱们讲的那些方法)
复制代码
// 时间格式的字符串
'2017-10-22' (IE下识别不了)
'2017/10/22 16:15:34'
'1508659621314'(若是传递的是距离1970年那个毫秒查,也能够识别转换的,可是只能是数字,不能是字符串)
类数组:相似于数组,可是不是数组
// for 循环操做
for(var i =0;i<ary.length;i++){
console.log(ary[i])
}
// for in 循环操做
for(var key in ary){
// key:属性名(数组中的属性名是索引)
console.log(ary[key]);
}
// for 循环只能遍历到数组私有的一些属性,而for in 循环能够吧一些自定义的公共属性也能遍历到
复制代码
数组中有不少方法
console.dir(Array.prototype)
复制代码
实现数组的增长、修改、删除
参数:一到多个,任何数据类型均可以,想要给数组末尾追加什么,直接传递到push方法中极客,传递多个逗号隔开
返回值:新增后数组的长度
原有数组改变了
参数:须要追加的内容(能够是多个任何数据类型的值)
返回值:新增后 数组的长度
原来数组改变了
把数组当作一个普通的对象,使用对象键值对的操做,给其设置新的属性(索引)
ary[ary.length]=xxx 向数组的末尾追加了新的内容
参数:无
返回值:被删除的那一项内容
原有数组改变了
参数:无
返回值:被删除那一项的内容
原有数组改变了
使用shift删除第一项以后,后面每一项的索引都要向前进一位(致使后面项的索引起生了改变)
把数组当作一个普通对象操做
delete删除:delete ary[索引]删除指定索引这一项(当前项被删除后),原有数组其它项的索引不会改变:当前数组的length也不会改变
ary.length--:删除数组最后一项
splice实现删除
splice(n,m):从索引n开始删除m个(m不写是个删除列数组的末尾,n也不写)
返回值:被删除的内容(以一个新数组保存)
原有数组改变了
splice(0) 清空数组
splice() 一项都不删除,返回一个新的空数组
splice(0,1)删除第一项
splice(n,m,x):在原有删除的基础上,用x代替删除的内容
splice实现增长
splice(n,0,x):在修改的基础上,咱们一项都不删除,把x插入到索引n的前面
ary.splice(0,0,x) 向数组末尾追加新元素
数组的查询
slice(n) 从索引n开始找到末尾
slice(0) /slice() 数组克隆,克隆一份和原来数组如出一辙的的新数组
slice支持负载索引,若是传递的索引为负数,浏览器解析的时候是按照总长度+负数索引 来处理的
concat:将多个数组拼接在一块儿
原有数组不变
slice: 数组的查询
参数: slice(n,m) 从索引n开始找到索引为m处(不包含m)
返回值:把找到的部分已一个新数组返回
原来的数组不变
slice(n) 从索引n开始找到末尾
slice(0) / slice() 数组克隆,克隆一份和原来数组如出一辙的新数组
slice 支持负数索引,若是传递的索引为负数,浏览器解析的时候是按照,总长度+负数索引 来处理的
复制代码
concat:将多个数组拼接在一块儿
参数:要拼接的内容(把内容放在原数组的后面),能够是一个数组,也能够是一些数据值
返回:拼接后的新数组
原有的数组不变
let arr = [0,100]
arr.concat([100,200],[200,300],12)
复制代码
concat() 什么都没有拼接,至关于吧原有数组克隆一份如出一辙的出来
实现吧数组转化为字符串(转换后的字符串逗号分隔每一项)
把数组按照指定的分隔符转换为字符串,和字符串中的split相对应
已知数组的每一项都是数字,想事先数组求和,咱们如何实现?
循环实现
var total = null;
for(var i=0;i<ary.length;i++){
total+=ary[i];
}
复制代码
利用join
var total = eval(ary.join('+')) // evel:把字符串变为js表达式执行
复制代码
把数组中每一项倒过来排序
实现数组的排序
参数:无或者回调函数
返回值:排序后的数组
原有数组改变
不传递参数的状况下:能够给10之内的数字进行升序排列,可是超过10的就没法处理(多位数值识别第一位)
ary.sort(function(a,b){
return a-b; //升序
return b-a; //降序
})
复制代码
获取当前如今数组中第一次或者最后一次出现的位置索引
if(ary.indexOf(12)>-1){
// 数组中包含12
}
复制代码
Array.prototype.myIndexOf = function myIndexOf(value){
var result = -1;
for(var i =0;i<this.length;i++){
if(value===this[i]){
result = i;
break;
}
}
return result;
}
复制代码
如下方法ie6-8下都不兼容
遍历数组中的每一项
ary.forEach(function(value,index){
/* 数组中有多少项,当前回调函数执行多少次,妹妹一次传进来的value就是当前遍历数组这一项的值,index 就是遍历这一项的索引 */
})
复制代码
遍历数组中的每一项,在forEach的基础上,能够修改每一项的值
ary.map(function(value,index){
/* 数组中有多少项,当前回调函数执行多少次,妹妹一次传进来的value就是当前遍历数组这一项的值,index 就是遍历这一项的索引 */
return xxx;
// return 后面返回的结果就是当前遍历的这一项修改成xxx
})
复制代码
filter
find
reduce
every
...
var ary = [1,2,3,4,5,6,7,1,3,4,5];
遍历数组的每一项,拿每一项和它后面的项依次比较,若是相同了,则把相同的这一项在原来数组中删除便可
/* * 新建一新数组,遍历传入数组,值不在新数组就push进该新数组中 * IE8如下不支持数组的indexOf方法 * */
function uniq(array){
var temp = []; //一个新的临时数组
for(var i = 0; i < array.length; i++){
if(temp.indexOf(array[i]) == -1){
temp.push(array[i]);
}
}
return temp;
}
var aa = [1,2,2,4,9,6,7,5,2,3,5,6,5];
console.log(uniq(aa));
复制代码
/* * 速度最快, 占空间最多(空间换时间) * * 该方法执行的速度比其余任何方法都快, 就是占用的内存大一些。 * 现思路:新建一js对象以及新数组,遍历传入数组时,判断值是否为js对象的键, * 不是的话给对象新增该键并放入新数组。 * 注意点:判断是否为js对象键时,会自动对传入的键执行“toString()”, * 不一样的键可能会被误认为同样,例如n[val]-- n[1]、n["1"]; * 解决上述问题仍是得调用“indexOf”。*/
function uniq(array){
var temp = {}, r = [], len = array.length, val, type;
for (var i = 0; i < len; i++) {
val = array[i];
type = typeof val;
if (!temp[val]) {
temp[val] = [type];
r.push(val);
} else if (temp[val].indexOf(type) < 0) {
temp[val].push(type);
r.push(val);
}
}
return r;
}
var aa = [1,2,"2",4,9,"a","a",2,3,5,6,5];
console.log(uniq(aa));
复制代码
/* * 给传入数组排序,排序后相同值相邻, * 而后遍历时,新数组只加入不与前一值重复的值。 * 会打乱原来数组的顺序 * */
function uniq(array){
array.sort();
var temp=[array[0]];
for(var i = 1; i < array.length; i++){
if( array[i] !== temp[temp.length-1]){
temp.push(array[i]);
}
}
return temp;
}
var aa = [1,2,"2",4,9,"a","a",2,3,5,6,5];
console.log(uniq(aa));
复制代码
/* * * 仍是得调用“indexOf”性能跟方法1差很少, * 实现思路:若是当前数组的第i项在当前数组中第一次出现的位置不是i, * 那么表示第i项是重复的,忽略掉。不然存入结果数组。 * */
function uniq(array){
var temp = [];
for(var i = 0; i < array.length; i++) {
//若是当前数组的第i项在当前数组中第一次出现的位置是i,才存入数组;不然表明是重复的
if(array.indexOf(array[i]) == i){
temp.push(array[i])
}
}
return temp;
}
var aa = [1,2,"2",4,9,"a","a",2,3,5,6,5];
console.log(uniq(aa));
复制代码
// 思路:获取没重复的最右一值放入新数组
/* * 推荐的方法 * * 方法的实现代码至关酷炫, * 实现思路:获取没重复的最右一值放入新数组。 * (检测到有重复值时终止当前循环同时进入顶层循环的下一轮判断)*/
function uniq(array){
var temp = [];
var index = [];
var l = array.length;
for(var i = 0; i < l; i++) {
for(var j = i + 1; j < l; j++){
if (array[i] === array[j]){
i++;
j = i;
}
}
temp.push(array[i]);
index.push(i);
}
console.log(index);
return temp;
}
var aa = [1,2,2,3,5,3,6,5];
console.log(uniq(aa));
复制代码
functoin [函数名](){
// => [函数体]
// 实现功能的具体js代码
}
复制代码
函数名(); // 建立的函数执行,并且这个函数能够执行不少次
函数名();
复制代码
每一次执行都至关于把函数体重实现功能的js代码重复执行了一遍
在真实的项目中,咱们通常都会把实现一个具体功能的代码封装到函数中
低耦合高内聚
咱们把以上的特色成为函数封装 (OOP面向对象编程思想,须要咱们掌握的就是类的继承、封装、多态)
函数做为js中引用数据类型中的一种,也是按照引用地址操做的
function sum(){
var total = 1+1;
total *= 20;
console.log(total.toFixed(2));
}
sum();
复制代码
私有做用域
(只能执行函数中以前编写的js代码)函数执行会造成一个私有的做用域,让里面的私有变量和外界互不影响(相互干扰、外面的没法直接获取里面的变量值),此时咱们能够理解为私有做用域把私有变量保护起来,咱们把这种保护机制称为为
闭包
做用域(全局做用域/私有做用域):提供一个供js代码执行的环境
全部的引用数据类型,他们须要存储的内容都是堆内存中(至关于一个仓库,目的是存储信息)
// 随便求出两个数的和
function sum(num1,num2){ //num1/num2就是形参变量(相似于var了一下)
var total = num1 + num2;
total*=10;
total=total.toFixed(2);
console.log(total);
}
sum(10,20);//10/20是实参 num1=10 num2=20
sum(10); // num1=10 num2=undefined 定义了形参可是执行的时候,没有传递实参,默认实参就是undefined
复制代码
当咱们不知道用户具体要传递几个值的时候(传递几个值都行),此时咱们没法设置形参的个数:遇到此类须要,须要使用函数内置的实参集合:arguments
function sum(){
console.log(arguments)
}
sum(10,20,'wjh',{name:'wjw'});
复制代码
function sum(){
console.log(arguments.callee.caller);//f
}
function fn(){
sum(10,20,'wjh',{name:'wjw'});
}
fn();
复制代码
// arguments.call或者arguments.call.caller通常真正项目中不多使用,由于是在严格js模式下不容许咱们直接使用这两个属性,然而现有项目大部分都是基于严格模式来的
// 任意数求和
function sum(){
var total = null;
for(var i =0;i<arguments.length;i++){
var cur = Number(arguments[i]);
!isNaN(cur)?total += cur : null
}
consloe.log(total);
return total;
// return 后面跟着的都是值(返回的都是值):此处很多TOTAL变量返回,而是吧total存储到值返回而已
// return 60;
}
sum(10,20,20);
sum();
sum(10,20,30,'wjw')
// console.log(total);
//=>Uncaught ReferenceError: total is not defined 闭包的保护机制致使做用域会保护里面的私有变量
复制代码
返回值是函数提供的一个出口:咱们若是想在外面使用函数私有的一些信息,那么就须要经过return,把这些信息返回出来供外面使用
sum:表明的是函数自己
sum() 让函数先执行,表明的是当前函数返回的结果(return)后面是啥,至关于函数返回的是啥
function sum(){
var total = 0;
renturn
}
console.log(sum());
// 若是函数中没有return或者return后面啥也没有,默认返回的结果是undefined
复制代码
function sum(){
var total = 0;
renturn;
console.log(sum());
// 函数体重遇到return后,return后面的代码都不在执行了
}
复制代码
没有名字的函数
oBox.onclick = function(){
// 把一个码云名字的函数(有名字的也无所谓)做为值赋值给一个变量或者一个元素的某一个事件等,函数表达式
}
复制代码
(function(n){
// 建立函数和执行函数放在一块儿,穿件完成立马之执行:自执行函数
// n 形参 n=10
})(10)
// 如下都是自执行函数,符号只有控制语法规范
~function(){}(10)
-function(){}(10)
+function(){}(10)
!function(){}(10)
复制代码