对象是一种数据的集合,数据格式为键值对。javascript
对象字面量以"{}"做为边界,由多个键值对组成,键与值经过":"隔开,键值对之间经过","隔开css
var obj = {name:"terry",age:12,gender:"male"};
使用系统内置的对象构造函数Object()html
var obj = new Object(); //等价于var obj = {}
obj是对象实例,构造函数是建立对象实例时使用的模板vue
使用自定义的对象构造函数,例Student()html5
var stu = new Student();
(用于读写)java
对象.属性node
var obj = {name:"terry",age:12,gender:"male"}; var name = obj.name; obj.name = 'terry';
对象[变量]mysql
var name = 'age'; obj[name];
打印出某个对象中全部的属性jquery
for(var key in obj){ }
依次从obj中获取属性名赋值给key,经过obj[key]访问属性值 (属性名若为变量,则必须经过中括号方式访问变量值)es6
将对象转换成字符串
方便网络传输(http/tcp/ip协议中不容许传输对象,只容许传输字符串和字节流),解决对象在io中传递的问题。
var obj = {name:'user'} obj.toString() //'[object Object]'
var obj = {name:'user'} JSON.stringify(obj) //'{"name":"user"}'
var qs = require('querystring') qs.stringify(obj)
全部构造函数的父构造函数,全部的构造函数都直接间接的继承Object。全部的实例对象均可以调用其构造函数及其父构造函数的原型中的方法:
Object.prototype.constructor() //输出建立该对象时使用的构造函数 Object.prototype.toString() //默认状况下输出[object object] Object.prototype.valueOf() Object.prototype.hasOwnProperty() //判断某一个属性是否是属于当前对象 Object.prototype.isPrototypeOf() //指定的对象是否在本对象的原型链中 Object.prototype.propertyIsEnumerable() //指定的属性是否可枚举 Object.prototype.toSource()
obj的构造函数是Object,因此obj能够调用Object.prototype的方法
var obj = {}
obj.toString();
arr的构造函数是Array,Array继承Object,所以,arr能够调用Array.prototype及Object.prototype中的方法
var arr = new Array(3);
arr.toString();
delete 对象.属性
对比java对象,js对象有哪些特殊的地方
1. js对象的属性能够被删除,java对象属性是固定的 2. js对象的属性能够随意添加,java对象属性是固定的 3. js对象能够经过字面量及构造函数来获取,java对象只能经过类构建
//student有且只能有两个属性 class Student{ private String name; private Integer age; public void setName(String name){ this.name = name; } public String getName(){ return this.name; } } Student student = new Student();
var obj = { name:"terry" //name是能够迭代的,是可读可写 }
假设:
当对象属性的值发生变化的时候,我想知道?
var obj = { _name:"alxe", age:0 }; Object.defineProperty(obj,"name",{ configurable:true, writable:true, //enumerable:true; 使用set、get时不设置enumerable、value //value:"terry", set:function(v){ this._name = v; console.log("名字被修改"); }, get:function(){ return this._name; } }) obj.name = "terry"; console.log(obj.name);
当name、age、gender属性发生变化的时候,都想检测到.
Object.defineProperties(obj,{ name:{ }, gender:{ } })
数组是由若干个元素组成,元素能够是任意的数据类型。经过索引(从0开始)访问元素,数组的长度经过length属性获取。
var arr = [8,1,20,3,2,9]
var arr = new Array(); // var arr = []; var arr = new Array(5); // var arr = [,,,,]; arr[0] = "terry" arr[1] = "larry" //["terry","larry"]
//es6出现 Array.of(2); //[2] Array.of(2,3) //[2,3]
console.log(arr[0]); console.log(arr[100]); // undefined
length可读可写,能够经过改变数组的长度来删除数组元素
arr.length
api --> 应用程序编程接口-使用别人编写的代码
关注函数改变的是不是原数组自己
遍历相关的方法
这些方法有个共同点,都须要传递一个回调函数做为参数,回调函数都有三个形参,分别为item,index,arr(可省略index/arr)
Array.prototype.forEach()
遍历数组对象
参数:回调函数
返回值:undefined
//模仿forEach写一个myForeach,其效果与forEach彻底相同 var arr = ["terry","larry","tom"]; arr.forEach(function(item){ console.log(item); }); //myForeach() Array.prototype.myForEach = function(handler){ //handler为一个回调函数 for(var i=0;i<this.length;i++){ var item = this[i]; handler.call(this,item,i) } } arr.myForeach((item,index)=>{ console.log(item,index) })
元素是否都知足同一个条件
参数:回调函数须要返回boolean
返回值:boolean
是否有元素知足同一个条件
参数:回调函数须要返回boolean
返回值:boolean
返回回调函数返回true的元素的集合
参数:回调函数须要返回boolean
返回值:数组
返回回调函数返回值组成的数组
参数:回调函数,必定要返回值
返回值:数组
栈、队列相关方法
向数组的末尾追加指定值
参数:任意值
返回值:数组长度
删除并返回栈顶元素
参数:无
返回值:删除的栈顶元素
出队列
参数:无
返回值:删除的队列首部元素
将指定元素插入到队列的首部
参数:任意值
返回值:插入后数组的长度
排序相关
原值发生改变;
Array.prototype.sort();
原值发生改变;
默认将数组元素转换为字符串,而后进行排序
sort容许接收一个比较器函数做为参数,比较器函数接受两个参数,
若是a > b,返回1,升序;若是a > b,返回-1,降序
arr.sort(function(a,b){ if(a>b){ return 1; }else{ return -1 } })
//提供一个函数,接受属性做为参数,要求按照name/age/grade进行排序 var arr = [{ name:"terry",age:19,grade:98 },{ name:"larry",age:12,grade:94 },{ name:"tom",age:15,grade:91 }] function sort(array,property){ array.sort((function(prop){ return function(a,b){ if(a[prop] > b[prop]){ return 1; } else { return -1; } } })(property)) } sort(arr,'age')
闭包:函数内部嵌套函数,内部函数拥有外部函数的变量,内部函数与外部函数的这个变量就组成了闭包。
截取
slice(begin,end)(原值不改变)
[1,2,3,4].slice(1); //[2,3,4] [1,2,3,4].slice(1,3); //数组个数为3-1
splice(begin,num,x,x,...)(原值改变)(功能更强大)
begin:开始位置,num:删除的元素个数,x,x,x:插入的元素
返回删除的元素组成的数组
[1,2,3,4,5].splice(2,2) //[3,4] [1,2,3,4,5,6].splice(3,0,2,2,2) //运行后的数组结果:[1,2,3,2,2,2,4,5,6]
var arr0 = JSON.parse(JSON.stringify(arr))
var arr1 = arr.slice(0)
var arr2 = [...arr]
拓展运算符(es6)
函数也是对象,是一个引用数据类型。
无论是普通函数仍是构造函数,本质是彻底同样的,只不过为了区分它们,咱们将构造函数的函数名大写
函数声明与var声明变量相似,都会有变量的提高。容许在函数声明前调用函数
let result = add(1,2); // 能够执行 function add( a, b){ return a + b; }
相似于普通的赋值表达式,变量会提高,可是函数初始化不会被提高。
add(); // 报错! var add = function(a,b){ return a + b; }
只有在函数的执行过程当中,内部属性才能被肯定
兜底对象(全局)
浏览器:window nodeJs:global
arguments
保存函数的全部实参,是一个类数组对象。
arguments.callee 指向当前函数,经常使用于递归函数。可是在严格模式'use strict'下没法使用
var foo = function(a,b){ console.log(arguments) //{'0':1,'1':2,'2':3} } foo(1,2,3)
//求阶乘 function foo(num){ if(num==1){ return 1; }else{ return arguments.callee(num-1)*num //更换函数名字时,不用考虑函数内部的名字更换 } }
this
当前的执行环境对象
与函数的调用方式有关
若是使用"()"调用函数,查看"()"是不是函数名,若是是,查看函数名前有没有点".",没有点"."this指向全局对象。有"."this指向点前面的那个对象。
function test(){ function bar(){ console.log(this) } bar(); } test(); //this-->global,由于调用bar()时,前面没有'.'
var foo = function(a,b){ return a+b; }
var foo = (a,b)=>{ return a+b; //a+b;若大括号内只有一条语句,且该语句为返回值语句,那么{}也可省略 } //箭头函数
箭头函数通常用于回调函数,是回调函数的简写。
箭头函数中的this指向包含它的外部函数的this,因此箭头函数通常放在外部函数里面,若箭头函数外没有外部函数,则this为{}。
function foo(){ ["terry","larry"].forEach((item)=>{ console.log(this,item); }) } foo(); //global foo.call({}) //{} foo.call({name:"terry"}) //{name:"terry"}
new Vue({ el:"#app", data:{ students:[] student{} }, methods:{ // 加载学生信息 loadStudents(){ // this 指向vue对象 $.get('/findAllStudent',(students)=>{ // this指向外部函数this,也就是指向vue对象 this.students = students; //自定义属性 }) } } })
函数是一种特殊对象,默认状况下,一个函数都会有一个原型对象与之对应,函数中有个指针prototype指向原型对象,原型对象中有个constructor指向函数,你中有我,我中有你。
fun.prototype.constructor === fun //true
函数能够做为返回值【函数定制】
var arr = [{age:12},{age:3}]; arr.sort((function(key){ return function(a,b){ if(a[key]>b[key]){ return 1; }else{ return -1; } } })('age'))
var pattern = /abc/igm //abc-->正则表达式 //igm-->模式
var pattern = new RegExp("abc","igm");
测试目标字符串是否匹配正则表达式
RegExp.prototype.exec();
从目标字符串中获取符合正则表达式的字符串
若是正则表达式中有修饰符‘g',在pattern中会维护lastIndex属性,即记录下一次开始的位置,当第二次执行exec()时,从lastIndex开始检索。若没有’g‘修饰符,则每一次都从开始位置进行检索。
var str = "my phone is 18812344321, my emil is licy@briup.com, my name is charles, my friend is jacky, his phone is 17751229900, my friend is tom, his phone is 15912344432." function search(str){ var pattern = /((188)|(177)|(159))\d{8}/g; var result; while(result = pattern.exec(str)){ console.log(result[0],pattern.lastIndex); } } //查询出全部符合模式的内容
独立学科,用于匹配字符串。经常使用于检索,论文查重,爬虫,表单验证。
默认是贪婪匹配,对于数量来讲,尽量多得去匹配。若是但愿非贪婪匹配,在数量词后添加?
var str = "hello world" var pattern = /\w{1,5}?/ //优先匹配1个字符
使用分隔符'|'分割供选择的字符,选择项匹配次序为从左至右。
url --> 协议://ip:port/path
var str = "my website url is http://127.0.0.1:80/cms/index.html , my database url is jdbc:mysql://127.0.0.1:3306/cms , this is ok" var pattern = /(http|jdbc\:mysql|ftp)\:\/\/(((\d{1,3})\.){3}((\d{1,3})))(\:(\d{2,4}))?(\/[\w\.]*)*/ig
每个括号都是一个分组
/(http|jdbc:mysql|ftp)://(w{1,3}.){+}:?(d{2,4})?(/[w.])/ig
pattern.exec(str)
result[0] 整个模式匹配的结果
result[1] 第一个分组匹配的结果
result[2] 第二个分组匹配的结果
...
1 引用第一个分组匹配的结果
var pattern = /(\d{1,3})\1/g; pattern.exec(192.12) //null pattern.exec(192.192.) //['192.192.','192.'...]
2 引用第二个分组匹配的结果
检索出全部的手机号。
(牛客网 - 正则表达式)
基本数据类型默认是没法调用Object原型中的方法,为了丰富基本数据类型的功能,即基本数据类型的变量也能够调用方法,js为此实现自动装箱功能【当调用基本数据类型变量的方法的时候,会自动转换为其构造函数的实例对象】
Number
var a = 3; a.toString(); //本来是没法调用该方法的,但因为js将其自动装箱,使其自动实现了‘a = new Number(a)’代码,即将其转换成为了引用类型的变量,所以其能够调用Number.prototype和Object.prototype中的方法 console.log(a); //当变量进行正常计算时,会将其自动拆箱
参数均可觉得正则表达式,若是为字符串,会先转化为正则表达式
String.prototype.split()
将字符串根据指定参数进行切割,返回一个数组
"hello".split() //['hello'] "hello".split("") //['h','e','l','l','o'] "terry#larry".split(/\#/) //['terry','larry'],等价于"terry#larry".split('#')
不支持全局搜索
与RegExp.prototype.test相似,返回匹配模式的字符串的索引,若是没有匹配的结果则返回-1
String.prototype.match()
与RegExp.prototype.exec相似
返回值为替换后的结果
返回截取后的结果,原值不改变
len表示截取的长度
返回截取后的结果,原值不改变
与slice相同
消除字符串左右两边的空格,原值不改变
...
构造函数
Date.prototype.getTime();
返回一个时间戳 ,即当前时间到格林威治标准时间的毫秒数(可使用时间戳转换成任意的数据格式)
var now = new Date(); //2020-08-10T05:48:49.439Z--当前时间 now.getTime(); //1597038529439--时间戳 var d = new Date(1597038529439) //2020-08-10T05:48:49.439Z
是对象,不是函数
向上舍入
向下舍入
如何建立一个对象?
字面量/Object - 纯对象,只能Object.prototype中的方法,而且类型没法细分。
类型细分(特定对象能够调用特定方法):
工厂函数模式
function PersonFactory(name,age,gender){ var p =new Object(); p.name = name; p.age = age; p.gender = gender; return p; } var p = PersonFactory("terry",12,"gender");//p本质仍是一个Object p.constructor // Object
问题:对象类型没法细分。
构造函数模式(构造函数使用new来调用)
function Person(name,age,gender){ this.name= name; this.age = age; this.gender = gender; this.sayName = function(){ console.log("my name is",this.name); } } //若是该函数使用new来调用,1) this指向当前实例对象2)函数执行完毕后,会将当前实例对象返回 var p1 = new Person("terry",12,"male"); // p1指向实例对象 var p2 = Person("terry",12,"male"); // p2为undefined,由于没有实例对象返回(this指向全局对象)
解决:对象类型细分的问题
问题:内存浪费。若是将函数存放到实例对象,每一个实例对象拥有一个独自的函数,而这样是毫无心义。
//解决了内存问题,但不成熟 function sayName(){ console.log("my name is",this.name); } function Person(name,age,gender){ this.name= name; this.age = age; this.gender = gender; this.sayName = sayName;//引用地址传递 }
构造函数(实例属性)+原型(实例方法,共享属性)
基本属性维护在实例中,共同的方法维护构造函数的原型中。
function Person(name,age,gender){ this.name= name; this.age = age; this.gender = gender; } Person.prototype.sayName = function(){ console.log("my name is",this.name); } Person.prototype.sayAge = function(){ console.log("my age is",this.age); } var p = new Person("terry",12,"male");
问题:原型方法封装性较差
加强版
function Person(name,age,gender){ this.name= name; this.age = age; this.gender = gender; } Person.prototype = { constructor:Person, // 核心点 sayName :function(){ console.log("my name is",this.name); }, sayAge :function(){ console.log("my age is",this.age); } } var p = new Person("terry",12,"female")//实例对象p的__proto__值指向的是其构造函数中prototype值所指向的原型对象。 //{}会建立一个新对象,同时将Person构造函数的prototype值指向该新创建的对象,而新对象的__proto__指向的倒是Object函数的原型对象的地址,若是调用‘p.constructor’返回的将是[Function:Object]。所以为了使其返回的是Person函数,咱们须要在这个新建立的对象中指明constrcutor所对应的构造函数为Person。
继承即实例对象能够调用其构造函数原型中的方法以及其构造函数的父构造函数原型中的方法...
Dog继承Animal
dog -> Dog.prototype -> Animale.prototype
function Aniaml(name,age){ this.name = name; this.age = age; } Animal.prototype = { constructor :Animal, sayName:function(){ console.log('my name is ',this.name); }, sayAge:function(){ console.log('my age is ',this.age); } } function Dog(name,age,gender){ //借用构造函数 Animal.call(this,name,age); /* this.name = name; this.age = age; */ this.gender = gender; }
Dog实例若想调用父构造函数原型中的方法,则要使用原型链继承。
//子构造函数的原型指向父构造函数的实例 Dog.prototype = new Animal();//继承 Dog.prototype.constructor = Dog; Dog.prototype.sayGender = function(){ }//其余操做必须在继承完成以后 var dog = new Dog('wang',12,'母')
dom -- > 浏览器将html/css转换为js对象,而后咱们经过js操做这些对象。
一般不多本身建立dom对象,由于浏览器已经转换了。但咱们须要在html中添加结构时须要本身建立dom对象,再由浏览器转换成html/css。
var dom = document.getElementById('');//document是浏览器的内置对象,浏览器将html转换成对象,此document表明的则是整个html页面。dom是js对象,是HtmlDivElement的实例对象,因此它能够调用HtmlDivElement,HtmlElemnet,Element,Node,Object中的方法
继承关系:
Node
Element 元素节点(标签转换的元素对象)*
Document 文档节点(表示当前html文档)*
节点信息相关属性
文本-3;注释-8;元素-1;文档-9
Node.prototype.nodeName
层次结构相关属性
Node.prototype.childNodes
返回一个类数组对象
var dom = document.getElementById("content"); var nodelist = dom.childNodes; //返回类数组对象 var arr1 = Array.prototype.slice.call(nodelist,0); //转换为数组方法一 var arr2 = Array.from(nodelist); //转换为数组方法二
方法
是经过父节点对象来调用
参数为true,表示除了克隆当前对象,还克隆子元素
Document.prototype.body
Document.prototype.forms
Document.prototype.images
Document.prototype.charset
Document.prototype.doctype 判断当前网页是html4仍是html5
方法:
元素节点查询
返回第一个匹配的element
返回全部匹配的element,并将其放入一个类数组对象中。
节点建立
var new_h3 = document.createElement("h3"); new_h3.innerText = "end" //该属性是HtmlElement内的属性
元素节点
设置标签内的文本节点
设置标签内的html代码(能够将字符串解析为标签)
获取(只能获取到内置样式)或设置样式
方法
将在将来的某个时刻执行,由浏览器调用,而且浏览器会将事件对象传递给该函数的参数。
事件类型
<a>标签有自动跳转的默认事件行为
事件冒泡
元素具备嵌套关系
<div class="outer"> <div class="center"> <div class="inner"></div> </div> </div>
(当咱们点击inner的时候,实际上也点击center、outer。)
事件捕获: outer -> center -> inner
但事件处理函数的调用默认是按照事件冒泡的顺序来调用
事件冒泡: inner -> center -> outer
操做的元素
事件源.on事件类型 = 事件处理函数(事件对象){
}
dom.onClick = function(event){
}
绑定方式:
事件的目标元素(操做的元素)
事件触发时候的坐标
阻止事件的默认行为
取消事件冒泡
将事件绑定在父元素上而不是子元素上
<body> <button id="add">添加</button> <table id="tbl"> <thead> <tr> <th>姓名</th> <th>操做</th> </tr> </thead> <tbody> <tr> <td>zyj</td> <td> <a href="" id="del">删除</a> <a href="" id="fix">修改</a> </td> </tr> </tbody> </table> <script> var $add = document.querySelector("#add"); var $tbl = document.querySelector("#tbl"); //添加 $add.onclick = function(){ var $new_tr = document.createElement("tr") $new_tr.innerHTML=` <td>`+Math.random()+`</td> <td> <a href="" id="del">删除</a> <a href="" id="fix">修改</a> </td> ` $tbl.children[1].appendChild($new_tr); } //删除 $tbl.onclick = function(event){ //事件绑定在父表格上,经过target,即点击的目标元素来确认具体事件行为。 var target = event.target; //每点击一次删除连接,该事件就会执行一次。 if(target.nodeName == 'A'){ switch(target.getAttribute("id")){ case "del": target.parentElement.parentElement.parentElement. removeChild(target.parentElement.parentElement); break; case "fix": alert("修改"); break; } } event.preventDefault(); } //下面的方法不可行,由于在html初次执行时就已经肯定了全部的删除连接,并设置了事件行为,但表格是动态增加的,即删除连接的个数也在动态增加。 // var delliset = document.querySelectorAll("#del"); // Array.from(delliset).forEach((item)=>{ // item.onclick = function(){ // item.parentElement.parentElement.parentElement.removeChild(item.parentElement.parentElement); // event.preventDefault(); // } // } </script> </body>
jquery 其实是对于dom api的封装,让用户使用dom方法变得更加简洁。
业务 | javascript | jquery |
---|---|---|
选择元素 | querySelector | 选择器$(" ") |
dom元素 | 没法进行批量操做 | 能够实现批量操做 |
事件绑定 | 兼容性较差 | 兼容性,高效,批量,方法简洁 |
dom层级关系 | 操做繁杂 | 操做简练 |
jQuery对象是一个类数组对象,类数组对象中的元素是Element元素
jquery对象 -> dom对象,即把类数组对象中的元素取出。
<script> var $btn_add = $("#add"); var $tbl_user =$("#tbl"); //删除 $tbl_user.on('click','a',function(event){ var target = $(event.target); switch(target.attr("id")){ case "del": // 移除节点 target.parents("tr").remove() break; case "fix": alert('修改'); break; } return false; }) // 添加 $btn_add.on('click', function(){ // 虚拟dom $( ` <tr> <td> <input type="checkbox"> </td> <td> `+Math.random()+` </td> <td> 男 </td> <td> <a href="" class="btn_del">删除</a> <a href="" class="btn_edit">修改</a> </td> </tr> `).appendTo($('#tbl > tbody')) }); </script>
//超时调用 var flag = setTimeout(function(){ //通过1000ms之后调用回调函数,只调用一次。1000ms不可靠 },1000) //flag为超时调用函数的一种标识 console.log(flag); //异步,先打印flag值 clearTimeout(flag); //取消超时调用
//间歇调用 var flag = setInterval(function(){ console.log('时间到了') //当回调函数的执行内容相同时,控制台只会显示一次输出内容 },1000) //每隔1000ms调用一次回调函数
如何使用超时调用来模仿一个间歇调用
(企业级不会直接使用这些提示框)
window.href = "" //window是浏览器的全局对象,var变量即被提高到window中
方法做用域,方法执行环境
方法执行完毕后,函数内部声明的变量会被释放
var a = 3; function foo(){ var b = 4; for(var i=0;i<10;i++){} console.log(i); //10--变量没有局部做用域 } foo(); console.log(window.a); //3 console.log(window.b); //undefined--方法做用域
如何模拟一个局部做用域
function foo(){ if(true){ var c = 1; //指望c拥有局部做用域 } console.log(c) //1 } ======================= function foo(){ (function(){ if(true){ var c = 1; } })(); }
window.onscroll = function(){ }
window.history.go(1); //前进1页 window.history.back();
window.onload = function(){ //当页面加载完毕后 var hash = window.location.hash.slice(1); //获取路由 switch(hash){ case "/space": break; case "/home": break; } }
异步的javascript和xml (json),主要用于先后台分离开发中数据的交互,占据咱们开发的50%以上。
//异步 function(){ 查询文章信息 ajax 查询用户信息 ajax 查询评论信息 ajax console.log('end'); } //三个查询同时进行,因为网络等缘由,返回结果的时间是不肯定的。所以,console.log("end")最早执行
//数据传递 -----同步方式(返回)----- function foo(){ return ""; } var a = foo(); -----异步方式(回调)----- function foo(handler){ 将来的某个时刻才能获取到 handler("结果") } foo(function(a){});
实现过程:
实例化XMLHttpRequest
var xhr = new XMLHttpRequest()
设置请求行
xhr.open(method,url)
设置请求头
(请求方式method = "POST"的时候才会设置Content-Type)
xhr.setRequestHeader(key,val)
设置请求体
(请求方式method = "POST"的时候才会传递data)
xhr.send(data)
监听请求状态
xhr.onreadystatechange = function(){ if(this.readyState === 4){ //请求正常发送到服务器端,响应到达客户端而且已被解析为客户端可用的格式 if(this.status === 200){ console.log(this.response); } } }
status:
200 ok 500 后端接口异常 404 找不到