javascript全程笔记
一、js基础
1.内核
谷歌 | WebKit |
---|---|
IE11 | Trident |
火狐 | Gecko |
safari | Webkit |
opera | Webkit |
2.javascript组成
1.ECMA Script :【规定了js的语法,类型,语句,关键字,操作对象等 ES6 2015.6】
2.Dom (document object model ) 文档对象模型
3.Bom (browser object model) 浏览器对象模型
二、数据类型
弱类型语言:变量类型是由它所包含的数据决定的
1.数据类型
1、typeof() 判断数据类型函数2、数值型number3、布尔bollean3、字符串string4、undefined5、null6、object
2.类型转换
(1)隐式类型转换:
(2)显式类型转换(强制类型转换)
Number() 【将其他数据类型转换成数值型】Number("12.23") //12Number(true) //1Number(false) //0Number("") //0Number("null") //0Number("undefined") //NaNNumber("NaN") //NaN
parseInt()console.log(parseInt("hello")) //NaNconsole.log(parseInt("23aa")) //23console.log(parseInt(12.23)) //12console.log(parseInt(0.12)) //0console.log(parseInt(true)) //NaNconsole.log(parseInt(false)) //NaNconsole.log(parseInt("")) //NaNconsole.log(parseInt(25,16)) //37 16进制数,输出10进制console.log(parseInt(25,8)) //21console.log(parseInt(1001,2)) //***9console.log(parseInt(25,10)) //25
NaN:not a Number 非数值【一个本来要返回数值的操作数,而没有返回数值的情况】
parseFlot()console.log(parseFloat("23.34")) //23.34console.log(parseFloat("23.45.78")) //23.45
3.进制转换
(1)其他进制转换成10进制
parseInt(25,16)parseInt(25,8)parseInt(25,10)parseInt(101,2)
(2)十进制转换成其他进制
v1 =23;v1.toString(16)v1.toString(8)v1.toString(2)v1.toString(10)
4. 常用方法
isFinite() //判断是否是正负有穷console.log(isFinite(200e500)) //falseconsole.log(isFinite(200e5)) //true
isNaN() //判断是否为非数值console.log(isNaN("hello")) //trueconsole.log(isNaN(true)) //falseconsole.log(isNaN(false)) //falseconsole.log(isNaN("10")) //false
(1)任何涉及NaN的操作,都返回NaN
console.log(NaN/8) //NaNconsole.log(NaN+8) //NaNconsole.log(NaN-8) //NaNconsole.log(NaN*8) //NaN
(2)NaN与任何值都不相等,包括t他本身NaN
NaN==NaN //false0/0 //NaN
5、常见面试题
console.log(null*5) //** 0 【隐式转换】
NaN*3 //NaN
undefined*5 //** NaN【undefined隐式转换undefined】
"hello"*5 //*** NaN【hello隐式转换NaN】
"23"+5 //235
"23"*5 //115
6、Boolean类型
/*true false*/ if(10>0){}else{ }if((10>5)==true){} 等价于 if(10>5){}if(!10>5){}
Boolean()
console.log(Boolean(23)) //trueconsole.log(Boolean(0)) //falseconsole.log(Boolean("hello")) //trueconsole.log(Boolean("")) //falseconsole.log(Boolean(null)) //falseconsole.log(Boolean(undefined)) //false
true false数值型 非空 0字符型 非空串 " "undefined 返回falsenull 返回falseobject 任意对象返回都是true
7. undefined类型
1、 变量只声明,未赋值
var a;console.log(typeof(a)) //undefinedalert(a) //undefined
2、 alert( c ) //报错
3、函数没有返回值,默认undefined
function f1(){alert("hello")}var r=f1()console.log(r) //undefined
4、调用函数时,应该提供参数,但没有提供,该参数返回undefined
function f1(a,b){alert(a);alert(b);}f1(3)console.log(r) //3 undefined
8、null 空类型 【对象】
var a=null
console.log(typeof(a)) //object null 是一种特殊的object
var b ={}
b.a=23
b.f1=function(){}
b=null
if(b==null){}
9、object 对象类型
对象就是一定属性和方法的封装体,通过对象能够引用到这些方法和属性
三、流程控制语句
1、
if(){}else if(){}else if(){}else{}
2、
switch(){case:语句体;break;case:语句体;break;case:语句体;break;default 语句体
}
3、
for(var i= 0;i<5;i++){语句体
}
for each / for in
4.while循环
5.do while 循环 至少执行一次
6、break 立即跳出循环
7、continue 停止当前循环,进入下一次循环
四、字符串操作
1.字符串创建
var s1 = "hello" var s2 = new String("hello")
2.属性
s1.length //获取字符串长度
3.方法
(1)获取字符【只能从正向走(从左到右)】
charAt()—————— //只能返回单个给定位置的字符
charCodeAt()————//返回字符编码ASCII码
var s1 = "hello" 01234----索引和下标值
var s2="fdhvfdhDD"
console.log(s2.charAt(3)) //v 返回单个给定位置的字符
var s2="fdhvfdhDD"
console.log(s2.charCodeAt(1)) //100 【位置1上的d Ascll码为100】
var s2=" fdhvf dhDD "
console.log(s2.charCodeAt()) //32 (space) 占位
console.log(s1[1]) //e返回给定位置的字符
console.log(s1[0]) //h
console.log(s1[2]) //l
(2)拼接字符串
+ | 字符串连接 |
---|---|
concat() | 用于将一个和多个字符串拼接起来,并返回新的字符串。 |
var s1="hello";
//var s2=s1.concat("world");
var s2=s1.concat("world","student","!"); //helloworldstudent!
(3)子字符串
1.substr(起始位置,长度)
substr(起始位置,长度) 从起始位置截取到指定长度的子字符串
如起始位置为负数,则倒数
var s1 = "hello world"console.log(s1.substr(3)) //lo world 后面是长度console.log(s1.substr(3,6)) //lo worconsole.log(s1.substr(0)) //hello worldconsole.log(s1.substr(-3)) //rld 从后往前定位,从左向右数console.log(s1.substr(3,-4)) //语法出错 长度不能是负数,为负数语法出错console.log(s1.substr(8,3)) //rld
2.substring(起始位置,终止位置)
substring(起始位置,终止位置):起始包含,终止不包含
遇到负数,自动转换为0
起始大于终止,则自动调换
console.log(s1.substring(3)) //lo worldconsole.log(s1.substring(3,7)) //lo wconsole.log(s1.substring(0)) //hello worldconsole.log(s1.substring(-3)) //hello world 负数转为0console.log(s1.substring(3,-4)) //hel 负数都转0 0-3提console.log(s1.substring(8,3)) //lo wo (3,8)调换位置
3.slice(起始位置,终止位置):
slice(起始位置,终止位置):起始包含,终止不包含
优点:识别负数
console.log(s1.slice(3)) //lo worldconsole.log(s1.slice(3,6)) //loconsole.log(s1.slice(0)) //hello worldconsole.log(s1.slice(-3)) //rldconsole.log(s1.slice(3,-4)) //lo w 3到-4console.log(s1.slice(8,3)) //
(4)字符串大小写转换
s1.toLowerCase() 小写
s1.toUpperCase() 大写
var s2="fdhvfdhDD"console.log(s2.toLowerCase()) //fdhvfdhddconsole.log(s2.toUpperCase()) //FDHVFDHDD
(5)去空格【s1.trim()】
s1=" he llo "
s1.trim() 去左右空格
var s2=" fdhvf dhDD "
console.log(s2.trim()) //fdhvf dhDD 去左右空格
(6)split (“指定的分隔值”,指定输出多少值) 字符串分割
s1 = "he,l,lo,wo,r,d"console.log(s1.split(",")) //[ "he", "l", "lo", "wo", "r", "d" ]console.log(s1.split("l")) // [ "he,", ",", "o,wo,r,d" ]console.log(s1.split(",",2)) /[ "he", "l" ] 输出俩个数组的值s2 = "hellowol"console.log(s2.split(",")) //[ "hellowol" ]没有“,”,原样输出console.log(s2.split(",",2)) //[hellowol]var s1="he!lloworld"m=s1.split("")console.log(m) //[ "h", "e", "!", "l", "l", "o", "w", "o", "r", "l","d" ]
(7)字符串位置方法【indexOf()】
indexOf():
1. 返回某个指定的字符串值在字符串中首次出现的位置。
2. 如找不到,返回-1, 第二个参数表示查找元素起始位置
lastIndexOf(): 首字母从后向前找,并不是位置从后往前数
var s1="hello world"console.log(s1.indexOf("e") ) //1console.log(s1.indexOf("o")) //4console.log(s1.indexOf("m")) //-1console.log(s1.indexOf("o",6)) //7
s1.lastIndexOf("o") //7s1.lastIndexOf("l") //9var s1="hello world"console.log(s1.lastIndexOf("e") ) //1
(8)replace替换
1)返回新字符串
2)只替换第一个匹配项
s1="hello"s2=s1.replace("e","m") //hmllos2=s1.replace("1","m") //hemlo
while(s1.indexOf("1")>-1){s1.replace("1","m")}
正则表达式:i-忽略大小写 g-全局查找 reg=/a/ig
s3=s2.replace(reg,"m")
(9)字符串删除
var s1="hello"
console.log(s1.replace("e","")) //hllo
console.log(s1.replace(s1[2],"")) //helo
//*删除字符串中所有的数字function f1(n1){for(var i = 0;i<n1.length;i++){if(n1.charCodeAt(i)>=49&&n1.charCodeAt(i)<=57){var a = n1.charAt(i)n1 = n1.replace(a,"") i=i-1}}alert(n1)} f1("he123llo")
(10)字符串的比较***
(1) localeCompare:调用本地操作系统
s1="abc"
s2="edf"
localCompare(s2)
s4= "yellow".localeCompare("yellow") //0
s4= "yellow".localeCompare("blue") //1
s4= "yellow".localeCompare("zoo") //-1
1.英文比较
v1.localeCompare(v2)
v1=v2 返回0
v1排在v2之前返回-1
v1排在v2之后返回1
s2= "3ellow".localeCompare("9oo") //-1
s3= "3ellow".localeCompare("3oo") //-1
s4= "3ellow".localeCompare("Zoo") //-1
2.中文比较–按拼音
s2 = "a".localeCompare("A")"北京".localeCompare("上海")alert("a">"A")//a1["哈尔滨","北京","杭州","上海","深圳"] 排序(升序)a1.sort((a,b)=>{retuwn a.localeCompare(b)}) //=>ES6函数a1.sort((a,b)=>{ //排序自带函数retuwn a.localeCompare(b)})console.log(a1)
(2)alert(“a”>“A”) //true 按ascii码比较
(11)字符串编码
(1)charCodeAt()
放索引
s1="a";console.log(s1.charCodeAt()) //97 对应的Unicode编码s2="海"console.log(s2.charCodeAt()) //28023 对应的Unicode编码
s1="a";s3=s1.charCodeAt();s2="罗"s4=s2.charCodeAt(0)console.log(s3,s4)s5=s4.toString(16);console.log(s5) //7f57
(2)fromCharCode()
根据ascii或unicode的十进制码进行解析
console.log(String.fromCharCode(65)) //A
console.log(String.fromCharCode(28032)) //海
(3)escape()
escape() 输出unicode码
unescape(“\u6D77”) 海
encodeURI(s1) //%E6%B5%B7 加密
decodeURI("%E6%B5%B7 ") 解密
s1 ="海"console.log(escape(s1)) //u6D77console.log(unescape("\u6D77")) //海console.log(encodeURI(s1)) //%E6%B5%B7 加密console.log(decodeURI("%E6%B5%B7 ")) //解密
五、操作符
1.算术操作符
= - * / % (取余)
a=a+1 ---> a++ a=a-1 ---> a--
++a 前置:先加减,后运算
a++ 后置:先运算,后加减
var a= 1;console.log(a) //1console.log(a++) //1console.log(a) //2var a= 1;console.log(a) //1console.log(++a) //2console.log(a) //2
// var a=1// b=a++ + ++a +a++// a=4 ****// b=7var a= 3;var b=a++ + --a+ ++a+a-- //14console.log(b)
+
console.log(0+0) //0console.log(-0+-0) //-0console.log(Infinity+Infinity) //ininfinityconsole.log(-Infinity+-Infinity) //-infinityconsole.log(Infinity+Infinity) //NaN
var c=false;console.log(c++) //0console.log(--c) //-1
2.赋值运算符
+= -= *= /= %=a=1;
a=a+3 --->a+=3
var a=12b=11c=a*=b+5c1=a/=b+3*(b+=4) ***c2=a++ -4*b--c3=b-- + a++*(a-=3 + ++b)// console.log(c) //192// console.log(c1) //3.4285714285714284***// console.log(c2) //-56.57142857142857***console.log(c3) //-37.244897959183675***
3.关系运算符
< = == ===【恒等于(严格比较)】 >= <= !=
a=2 数字型b="2" 字符型a==b //truea===b //false
==代表相同,先检查两个操作数的数据类型,发现不同。可进行类型转换,再进行值的比较,如果相同,则调用===比较null==undefined //true 都是空===严格相同,如果类型不同,直接判断不同类型不同,一定不相等 null===undefined //trueNaN===NaN //false 值很多console.log(null===null) //true 按空算【不是转number】console.log(undefined===undefined) //true 按空算【不是转number】
console.log(NaN==NaN) //falseconsole.log(NaN===NaN) //falseconsole.log(null==0) //falseconsole.log(undefined==0) //falseconsole.log(true==1) //trueconsole.log("Black">"Mick") //比较ASCII吗console.log("23"<"3")console.log("a"<"3")
4.逻辑运算符
&& -------> 都为真才为真,
|| ------>一个为真才为真
! ------>真变假,假变真
短路运算符——js依次获取每一个操作数,将他们转换为布尔变量,如果是false, 则中断后面的处理,返回这个操作数的值,否则继续处理下一个操作数,返回最后操作数的值,以上称为逻辑判断的短路运算
var a=100var b=falsevar c=(b&&(a=25))console.log(a) //100 &&不进行后面运算var A="1" && true && 0 && false && "abc" //A=0 false为假
特殊例子
console.log(-0+-0) //-0console.log(Infinity+Infinity) //NaNconsole.log(Infinity*0) //*NaNconsole.log(0/0) //NaN 0不能做分母console.log(Infinity/Infinity) //NaNconsole.log("m"+1+1) //m11console.log(1+1+"m")//2mconsole.log("m"+(1+1))//m2var b="001" //当作1来用console.log(b++) //1console.log(b--) //2****console.log(NaN==NaN) //falseconsole.log(NaN===NaN) //false
5、typeof
console.log(typeof(1)) //numberconsole.log(typeof(NaN)) //numberconsole.log(typeof(Number.MAX_VALUE)) //numberconsole.log(typeof(Number.MIN_VALUE)) //numberconsole.log(typeof(Infinity)) //numberconsole.log(typeof("123")) //stringconsole.log(typeof(true)) //booleanconsole.log(typeof(Date)) //functionconsole.log(typeof(c)) //undefinedconsole.log(typeof(undefined)) //undefinedconsole.log(typeof([])) //objectconsole.log(typeof(Math)) //objectconsole.log(typeof(window)) //objectconsole.log(typeof(document)) //objectconsole.log(typeof(null)) //object
(1)数值类型 typeof返回number
console.log(typeof(1)) //numberconsole.log(typeof(NaN)) //***numberconsole.log(typeof(Number.MAX_VALUE)) //numberconsole.log(typeof(Number.MIN_VALUE)) //numberconsole.log(typeof(Infinity)) //number
(2)字符串类型,typeof返回 string
typeof("123") //string
(3)布尔类型,typeof返回boolean
typeof(true) //boolean
(4)对象、数组、null、typeof返回object
console.log(typeof([])) //objectconsole.log(typeof(Math)) //objectconsole.log(typeof(window)) //objectconsole.log(typeof(document)) //objectconsole.log(typeof(null)) //object
(5)函数类型,typeof返回function
function f1(){}console.log(typeof(eval))console.log(typeof(f1));console.log(typeof(Date)) //function
(6)未定义的便力量或undefined,typeof返回 undefined
六、位运算符
【转换成二进制进行运算】
1.定义
& 与 都为1结果为1| 或 只要有1结果为1^ 异或 相同为0不同为1~ 非 0变1,1变0 *****>> 右移<< 左移
2.非运算
~正数 ~n=> -(n+1) ~负数 (|n|-1)
console.log(3&2) //2
【转化为二进制数011 & 010———> 相同为1,不同为0——> 010=>2】 console.log(3|2) //3011 | 010==>011=>3console.log(3^2) //1console.log(~3) //-4
【011——>(取反)100——>减一011——>再取返100 变符号位】console.log(~25) //-
11001 00110 00101*** 11010console.log(25&3) //1console.log(25|3) //27console.log(25^3) //26console.log(~25) //-24console.log(~(-27)) //26console.log(64>>5) //2console.log(255&85) //85
3.三元(目)运算符
a=10if(a>0){alert("yes")}else{alert("no")}
————>a>0?alert("yes"):alert("no")c=a>0?alert("yes"):alert("no")
七.js内置对象
Date Math(数学运算)
1. Date 日期对象
var s1=new Date() d1.getDate() 日d1.getDay() 星期 1 2 3 4 5 6 0-星期日d1.getHours() 小时 1.23 0d1.getMinutes() 分钟 1.59 0d1.getMonth() 月 0.11d1.getSeconds() 秒 1.59.0d1.getTime() 返回1970.1.1午夜(零时)开始到当前时间的“毫秒”数d1.getFullYear() 年
1.格式化日期对象
console.log(s1.toLocaleDateString())
console.log(s1.toLocaleString())
console.log(s1.toLocaleTimeString())
var s1=new Date() console.log(s1.toLocaleDateString()) //2022/7/11console.log(s1.toLocaleString()) //2022/7/11 23:22:43console.log(s1.toLocaleTimeString()) //23:22:43
----原型封装-----
对象
Date.prototype
Date.prototype.formatDate=function(type){var t=new Date()var a=t.getFullYear()var b=t.getMonth()+1var c=t.getDay()switch(type){case "-":return a+"-"+b+"-"+c;break;case "/":return a+"/"+b+"/"+c;break;case ".":return a+"."+b+"."+c;break;default: return a+"年"+b+"月"+c+"日"}}var d2= new Date()var ndate=d2.formatDate("-")alert(ndate)
日期格式化—升级版
formatdate(“yyyy-MM-dd hh:mm:ss”)//年月日,
时分秒:formatdate(“yyyy-MM-dd”)
2. Math
1.基础
abs()———— 绝对值
sqrt(4)————2 开平方
pow(2,3)————2^3 返回X的Y次幂的值
2.浮点数测
(1)ceil() ————向上取整
(2)floor()————向下取整
(3)round()————四舍五入
(4)v1.toFixed()————截取位数,四舍五入【截取小数】
(5)sin(30)三角函数 -1~1之间
//23.67——23.7 round 【四舍五入,保留一位小数】
console.log(Math.round(23.67*10)/10);
3. random 随机数
每刷新一次都会出现一个新的数 Math.random()
返回0-1之间的随机浮点数——不包含0,1。
//(1)返回1-10之间的随机整数a=Math.random()*10+1console.log(Math.floor(a))
//(2)返回0-10之间的随机整数Math.round(Math.random() * 10) //0-9Math.floor(Math.random()*11) //0-10【0.99*11=10.89】
//(3)返回指定范围的随机整数f1(10,200) 包含10和200//【1】f1(起始,终止) 包含起始和终止console.log(Math.floor(Math.random()*(20-10+1))+10)Math.floor(Math.random() * (max - min + 1)) + min;//【2】f1(起始,终止) 包含起始和不包含终止console.log(Math.floor(Math.random()*(20-10))+10)//【3】f1(起始,终止) 不包含起始和不包含终止console.log(Math.ceil(Math.random()*(20-1-10))+10)
//生成随机数,随机数去重,上下范围0.1function random_fun(rdata,min,max) {var r_number = (Math.random() * (max - min) + min).toFixed(1)if (rdata.length > 0) {if (rdata.indexOf(r_number) > -1) {return random_fun(rdata, min, max)}}}
八、数组
数组定义:数组是保存任意类型的数据结合
1.构建数组
(1)构造函数方式实现var a1=new Array() '空'数组
(2)直接量实现var a2=[]
2.数组数据操作
(1)a1[0]赋值
var a1=[]a1[0]="hello"console.log(a1)var a1=["q","b","c"]console.log(a1[1]) //b
(2)长度 var a1=new Array(3) 指定长度(3)
var a1=new Array(3) 指定长度(3)console.log(a1[0]) //undefined【相当于申明未赋值】
var a1=new Array(3) console.log(a1[0]) //undefinedconsole.log(a1.length)//3var a2=[,,,,] //最后一个逗号忽略,所以按4来提console.log(a2[2]) //undefinedconsole.log(a2.length)//4
3.数组的遍历【数组下标由0开始】
var a1=[23,35,34,13](1)for(var i=0;i<a1.length;i++){console.log(a1[i])}(2)for infor(var i in a1){console.log(a1[i])}
4. 数组去重
var arr1=[23,45,23,56,45,89] 去重 arr1=[23,45,56,89]//生成[1..36]数组,随机选择5个数,不重复// 如:12 23 3 7 29// var a=[];// var t=0// for(var i=0;i<=35;i++){// a[i]=i+1;// }// var n=[]// while(t!=5){// var num=parseInt(Math.random()*36)// if(n.indexOf(a[num])==-1){// n[t]=a[num]// t++// }// }// console.log(n)
5.数组的添加与删除——[push() unshift()]
1. 尾部增加:push() 数组尾部增加一个或多个数据,对原数组进行修改,返回修改后的数组长度 。
2. 尾部删除:pop() 删除数组尾部的一个元素,对原数组进行修改,返回的是被删除的元素
3. 头部增加:unshift( ) 数组的头部增加元素,对原数组进行修改,返回修改后的数组长度
4.头部删除:shift() 删除数组的头部元素,对原数组进行修改,返回被删除元素
var a=[12,32,19,4,23]a.push(54)console.log(a) //[ 12, 32, 19, 4, 23, 54 ]b=a.push(54)console.log(b) //6
var a=[15,32,12,4,42]a.pop()console.log(a) //[ 15, 32, 12, 4 ]
var a=[15,32,12,4,42]// a.unshift(23)// console.log(a) //[ 23, 15, 32, 12, 4, 42 ]console.log(a.unshift(23)) //6
var a=[15,32,12,4,42]a.shift()console.log(a) // [ 32, 12, 4, 42 ]console.log(a.shift()) //32
九、数组的操作方法
1.reverse()
对原数组进行反转,不会创建新数组
var a1=[23,12,56,34]
console.log(a1.reverse()) //[34,56,12,23]
2.join ()
可以指定分隔符,指定分隔符将数组转化为字符串,生成新的字符串
(1) 字符串转数组
var a1="he,ll,oo,mm"var a2=a1.split(",") //[ "he", "ll", "oo", "mm" ]字符串默认带双引号
(2) 数组转字符串
a2.join(" ")
var a1= [ "he", "ll", "oo", "mm" ]a2=a1.join("")console.log(a2) //helloommconsole.log(typeof(a2))a2.join("3") //he3ll3oo3mm
var a1=[2,3,4] //alert只接收字符串a2=a1.toString()console.log(a2) //2,3,4
(3) concat
- 连接数组,将数据加到末尾
- 不修改原数组,生成新数组
- 只能打散一维数组,不会打散数组中包含的数组
a1=[1,2,3]
a2=[4,5,6]
a1.concat(a2) //[1,2,3,4,5,6]
a1.concat(55,66) //[1, 2, 3, 55, 66]
a1.concat([33,88],[44,77]) //[1, 2, 3, 33, 88, 44, 77]
a1.concat([[11,22]],[33,44],"abc") //[1, 2, 3, [11, 22], 33, 44, 'abc']
(4) slice : 截取子数组
(1) 不修改原数组,生成新数组
(2) a2=a1.slice(2,4) 起始包含,终止不包含
(3) a2=a1.slice(2) 从起始到数组末尾
(4) a2=a1.slice(-4,-2) 如为负数从右到左截取
var a1=[12,34,45,67,89]a2=a1.slice(2,4) //[45, 67]a2=a1.slice(2) //[45, 67, 89]a2=a1.slice(2,10) //[45, 67, 89]a2=a1.slice(-4,-2) // [34, 45] 负4查到负2【起始包含,终止不包含】12,34,45,67,890 1 2 3 4-5 -4 -3 -2 -1
(5) splice 增加和删除元素
修改原数组,返回删除的元素
splice(arg1,arg2,arg3…)
arg1————起始位置
arg2————被删除的元素个数
arg3及后面的所有参数————要插入的元素
a1=[1,2,3,4,5,6,7]a1.splice(1,2,3,4,5)console.log(a1) //[1, 2, 3, 4, 5, 6, 7]a1.splice(2)console.log(a1) // [1, 2]
//a1.splice(2) //如只有一个参数,从起始位置删除后面的所有元素a1.splice(2,2)console.log(a1) //[1,2,5,6,7]a1.splice(2,0)console.log(a1) //[1, 2, 3, 4, 5, 6, 7]a1.splice(2,0,0,0,0)console.log(a1) //[1, 2, 0, 0, 0, 3, 4, 5, 6, 7]a1.splice(6,2,3,4)****console.log(a1) //[1, 2, 3, 4, 5, 6, 3, 4]//六位开始,删除2位数,不够就只删一个,向后补arg3及后面的所有参数[34]a1.splice(-2,-3,6,7,8) console.log(a1) // [1, 2, 3, 4, 5, 6, 7, 8, 6, 7]
//如果第一个参数为负数,则从右到左查找, 如第二个参数为负数,按0处理
(6) 数组删除
- splice()
- delete 删除元素本身,不能删除空间,不改变数组大小
var a1=[2,3,4]delete a1[0]console.log(a1) //[empty, 3, 4]console.log(a1.length) //3
(7) 字符串拼接的操作效率
var s1="hello"var sums1=""var arr1=[]var begintime=new Date().getMilliseconds()
// for(var i=0;i<1000000;i++){
// sums1=sums1+s1 //耗时最多
// }
// for(var i=0;i<1000000;i++){
// sums1.concat(s1)
// }for(i=0;i<1000000;i++){arr1.push(s1)}arr1.join("")var endtime=new Date().getMilliseconds()console.log(endtime-begintime)
(8) 数组检测
var a1=[2,3,4] console.log(typeof(a1)) //object
数组检测
1. Array.isArray(a1) //true
2. if(a1 instanceof Array){ } //true
3. if(a1.constructor==Array){ } //true
var a1=[2,3,4]// console.log(Array.isArray(a1)) //trueif(a1 instanceof Array){console.log(true)}//trueif(a1.constructor==Array){console.log(true)}//true
(9) 数组的toString()
所有对象都有toString() valueof() toLocalstring()
toString():返回每个值的字符串形式,以 " , "拼接数组转字符串
扩展:
var a1=[2,3,4] //alert只接收字符串a2=a1.toString()console.log(a2) //2,3,4// p1={"name":"zs"}// console.log(p1)// console.log(p1.toString()) //[object Object]p1={"name":"zs",toString:function(){return "hello"}}console.log(p1.toString()) //hello
5.封装原型函数:toArray()
方法一:String.prototype.toArray=function(arr){arrNew1=arr.split("")return arr}var arrNew2=new String().toArray("abcd")console.log(arrNew2)方法二:String.prototype.toArray=function (a){var b=[]for(i=0;i<a.length;i++){b= b.concat(a.charAt(i)) }return b;}var f= new String().toArray("abcd")console.log(f)
方法三:String.prototype.toArray=function(){arr=this.split("")return arr}var x="abcd".toArray()console.log(x)
(10) 数组下标
var a1=[4,5,6,7]
1.a1[0] 0----下标
2.范围 :【大于0 小于 2^32 -1整数】
3.如下标是负数,浮点数,布尔型等,js会自动将其转换为字符串
var a1=[4,5,6,7]// console.log(a1[true]) //undefinedconsole.log(a1[-2]) //undefinedconsole.log(a1[2.3]) //undefined4. 下标是可以不断递增的表达式****var a1=[] for(var i=0;i<10;i++){a1[i++]=i}
(11) sort 排序
sort排序
数组.sort(比较函数)
比较函数——具有两个参数f1(a,b)
函数值判断返回值返回值大于0 a排在b的后面返回值小于0 a排在b的前面返回值等于0 a,b不动
1.var a1=[23,,4,5,12,78,16]a1.sort()console.log(a1) //[12,16,23,4,5,78] localcompare()先比较第一位,在比较第二位2. var a1=[23,4,5,12,78,16]function f1(a,b){//return a-b a在b的后面if(a-b>0){return 1 //a在b的后面}else if(a-b<0){return -1 //a在b的前面}else{return 0 //a b不动}}a1.sort(f1)console.log(a1) //[4, 5, 12, 16, 23, 78]
3.数组函数
1. indexOf
返回数组中第一个找到的元素的位置,不存在返回-1
var a1=["ab",23,45,67]var a2= a1.indexOf("ab")console.log(a2) //0
2. forEach
数组.forEach(function(当前元素值【元素本身】,当前元素索引,数组对象){})
var a1=["a","b","v",7,8]for(var i=0;i<a1.length;i++){a1[i]}// a1.forEach(function(item,index){//放的要调用的函数 item元素本身,index索引// console.log(item,index)// })a1.forEach(function(item,index,arr){//放的要调用的函数 item元素本身,index索引console.log(item,index.arr)})
for(var i=0;i<10;i++){arr[i]循环体}for(var i in 数据结合){arr[]循环体}
扩展:前后台数据传输格式
{ } json / 对象
{“name”:“zs”,“age”:23,“number”:“00123”}
{“name”:“ls”,“age”:23,“number”:“00123”}
{“name”:“ws”,“age”:23,“number”:“00123”}
var data=[{"name":"zs","age":23,"number":"00123"}{"name":"ls","age":23,"number":"00123"}{"name":"ws","age":23,"number":"00123"} ] data1[0].namedata1[1].agedata1[2].number
3.map
a1.map(function(item,index)(){ })
对数组每一项进行遍历 [返回一个新的数组]
a1=[3,4,5,6] 生成 a2=[6,8,10,12]var a1.map(function(item,index,arr){return item*2})
var data1=[{"name":"zs","age":23,"number":"00123"},{"name":"ls","age":23,"number":"00123"},{"name":"ws","age":23,"number":"00123"} ] //data1[0].name//data1[1].age//data1[2].numbervar Maxage=0data1.forEach(function(item,index,arr){console.log("名字:"+data1[index].name+"年龄:"+data1[index].age+"号:"+data1[index].number)Maxage=data1[index].age+Maxage;})console.log(parseInt(Maxage/3))
map 与forEach区别
1.forEach只是遍历,而map能够生成新的数组
2.map效率要比forEach速率快
3.map可以进行链式操作
var a1=[3,4,5,6]var a2= a1.map(function(item,index,arr){return item*2}).map(function(item1){return item1*10}) //console.log(a2)
4. filter(过滤器)数据过滤
arr.filter(function(当前元素值,当前元素索引,数组对象){})
(1) 返回新数组,不对原数组进行修改,
(2) 对返回”true“的结果过滤,false的结果忽略。
var a1=[10,20,10,30,40,50,20,40]a2=a1.filter(function(item,index,arr){if(arr.indexOf(item)!==index)return true})console.log(a2) //[ 10, 20, 40 ]
5. reduce()
接收一个函数作为累加器,数组中的每一个值,从左到右开始缩减
最终计算为一个值
arr.reduce(function(初始值,当前元素值,当前元素索引,数组对象){},初始值(可省略))
6. some()
判断数组中是否有满足条件的元素
(1)a1.some(function(item,index,arr){})
(2)函数内部,返回true,找到了满足条件的元素,则循环结束
返回false,没找到,循环继续
(3)函数的执行次数不一定等于数组长度
> //a1=[10,30,60]判断数组是否有大于20的元素a1.some(function(item,index,arr){return item>20})console.log(a2)
7. every()
检测数组中所有元素是否都满足条件
(1)a1.every(funnction(item,index,arr){})
(2)有一项不满足就返回false,都满足才返回true
(3)函数的执行次数不一定等于数组长度
var a1=[10,30,5,60]a2=a1.every(function(item,index,arr){return item >0})console.log(a2)
4.浮点精度
1.产生原因
js数值型不管是整数,还是浮点,都是Number类型 ,通通按64位表示【弱类型语言:给啥就是啥】
最高位--符号位 存储指数 尾数位(有效数位)---超出部分自动舍弃1 11位 52位
0.10.0001 1001 1001 1001....(1100的循环)
0.20.0011 0011 0011 0011....(0011的循环)
754 标准的 64 位双精度浮点数的小数部分最多支持53位二进制位,多余的会被舍去,产生误差
2.解决方法
(1)乘以10,再计算(0.1*10+0.2*10)/10=0.3
(2)toFixed() 截取位数,四舍五入a=0.1+0.2a.toFixed(1) //0.3
(3)第三方库
3.tofixed()的局限性
var a=1.35console.log(a.toFixed(1)) //1.4console.log(1.336.toFixed(2)) //1.34console.log(1.3335.toFixed(3)) //1.333
4.优化tofixed()
【对toFixed()进行封装】
//方法1Number.prototype.mytoFixed=function(b){var a = this.toString()var c = (a.substring(0,a.indexOf(".")+1)).lengthvar num =String(a).substring(0,c-1+b)if(String(a)[c+b] >= 5){num = num + (Number(String(a)[c-1+b])+1)}else{num = num + (String(a)[c-1+b])}return num}var a = 11.334console.log(a.mytoFixed(2))
将获取的小数转换为字符串 根据小数点的下标判断截取小数位数的下标 判断截取小数的后一位 四舍还是五入 对截取小数位进行操作
// 方法2
function myFixed(num, digit) {
if(Object.is(parseFloat(num), NaN)) {return console.log(`传入的值:${num}不是一个数字`);
}
num = parseFloat(num);
return (Math.round((num + Number.EPSILON) * Math.pow(10, digit)) / Math.pow(10, digit)).toFixed(digit);
}
//方法3Number.prototype.mytoFixed=function(num,n){var a=num.toFixed(n+1)-num.toFixed(n)var b=a.toFixed(n+1)*Math.pow(10,n+1)if(b==5||b==6){return (Number(num.toFixed(3))+Number(Math.pow(0.1,n).toFixed(n))).toFixed(n)}else{return num.toFixed(n)}}var a=new Number().mytoFixed(1.335,2)console.log(a)
用toFixed获取需要截取位数的后面那一位,该位置上的数若等于5或者6,就让截取位上的数加1,否则返回正常的toFixed用法
5.包装类型
包装类型(引用类型之一):Number Boolean String 用new形式创建
基本数据类型 :string (s1=“hello”)
1、包装类型中的String
(1) new String() new创建
(2) typeof() 返回object
(3) s2=new String(1,2,3,4)当有多个参数时,只处理第一个,只输出1
(4) s1=new String(++n,n++,++n)当有多个参数时,虽然只处理第一个, 但js会将所有代码执行完,所以n=4
s1="hello" //后台操作——s1=new String("hello")s1.substring(2) s2=s1.substring(2) //方法必须是对象, 但在此处s1=new String("hello")s1=null 销毁
var s1="hello"s2=new String("hello")console.log(typeof(s1)) //stringconsole.log(typeof(s2)) //object
var n=1s1=new String(++n,n++,++n)console.log(s1) //2console.log(n) //4s2=new String(1,2,3,4)console.log(s2) //1
2、包装类型中的 Boolean
v1=falsev2=v1&&true false
v1 =new Boolean(false)v2 =v1&&trueconsole.log(v1) //Boolean { false } 是对象console.log(v2) //true v1强制转换成对象为true
(1)
var v3=falsev4=new Boolean(false)console.log(typeof(v3)) //booleanconsole.log(v4) //Boolean {false}包装对象console.log(v3 instanceof Boolean) //false
(2) instanceof 判断是否是对象实例
v3 instanceof Boolean //falsev4 instanceof Boolean //true
3. 包装类型的Number
var v1=23v2=new Number(23) console.log(v1) //23 numberconsole.log(v2) //Numberconsole.log(v1 instanceof Number) //falseconsole.log(v2 instanceof Number) //true
6.值类型与引用类型
1、值类型
值类型的传递空间大小固定,采用基本数据类型string number null undefined
存储在栈内存中,
占据的空间是固定的
2、引用类型
引用类型采用地址传递: 数组(array),函数(function),对象(object)
堆中存储的一般都是对象,通过一个地址编号(也叫引用指针)传递给栈内存的变量
读取数据的时候,由引用指针(地址编号)到堆内存中查找数据块
占据的空间是不固定的
3、 值传递,引用类型传递
var a=2function f1(x){x=4}f1(a)console.log(a) //2值传递a1=[1,2,3]function f1(x){x[0]=50}f1(a1)alert(a1[0]) //50引用类型地址传递
7、拆箱与装箱
装箱:将值类型包装为对应的引用类型对象
var a=12b=new Number(12) 装箱
拆箱:将引用类型转换为值类型 valueof()
c =new Number(23)var d=c.valueOf()typeof(d) number
8.深拷贝与浅拷贝
1.浅拷贝
针对都是引用类型,拷贝基本数据类型不受影响,拷贝引用类型源对象会被修改,仅拷贝对象地址
白话文:假如b复制了a,当修改a时,b也跟着变化【b复制a,改a,b变】
a1=[1,2,3]a2=a1console.log(a1,a2) //数组123a1.push(4)console.log(a1,a2) //数组1234
2.深拷贝:
拷贝一个对象之前,先给拷贝到对象创建一个堆地址, 这样当拷贝到对象指向堆中的数据,被拷贝的对象不会改变。
白话文解释:b复制了a,当修改a时,b也不变 实现深拷贝的方法【b复制a,改a,b不变】
(1) 创建新数组,for循环复制
/*深拷贝处理*/var a1=[1,2,3]a2=[]for(var i in a1){a2.push(a1[i])}a1.push(4)console.log(a1,a2)//a1[1,2,3,4] a2[1,2,3]
(2)数组方法slice
var arr1 = [1,2,3];var arr2 = arr1.slice(0);arr2[1] = 7;console.log("数组的原始值:" + arr1 ); //数组的原始值:1,2,3console.log("数组的新值:" + arr2 ); //数组的新值:1,7,3
3.数组方法concat
var arr1 = [1,2,3];var arr2 = arr1.concat();arr2[1] = 7;console.log("数组的原始值:" + arr1 ); //数组的原始值:1,2,3console.log("数组的新值:" + arr2 ); //数组的新值:1,7,3
4.Json.parse(JSON.stringfy)
【弊端:只能拷贝Number, String, Boolean, Array, 扁平对象,即那些能够被 JSON 直接表示的数据结构。】
var arr1 = ["1","2","3"];var arr2 = JSON.parse(JSON.stringify(arr1));arr1.push(4)console.log(arr1) //[ "1", "2", "3", 4 ]console.log(arr2) // [ "1", "2", "3" ]
var test={a:"ss",b:"dd" };var test1 = JSON.parse(JSON.stringify(test));test.a="cc"console.log(test); //Object { a: "cc", b: "dd" }console.log(test1); //Object { a: "ss", b: "dd" }
var test={name:"hyw",age:23 ,friends:["dwz1","dwz2","dwz3"] };var test1 = JSON.parse(JSON.stringify(test));//拷贝数组,注意这行的拷贝方法test.friends[0]="dwz4"console.log(test); //Object { name: "hyw", age: 23, friends: (3) […] }console.log(test1); //Object { name: "hyw", age: 23, friends: (3) […] }
5. 手动封装深浅拷贝
copyfun(对象,true) true进行深拷贝 false进行浅拷贝return 拷贝后的对象
var a1=[1,2,3]
a2=copyfun(a1,false) //浅拷贝 a1变,a2变
a3=copyfun(a1,true) //深拷贝 a1变,a3不变typeof(obj) 判断对象
a1 instanceof Array 判断数组
Object.prototype.copyfun=function (a,b){if(typeof(a)=="object"){if(b==true){return a2=JSON.parse(JSON.stringify(this))}else{return a3=a}}else{return a1=a}}var f1=([1,2,3])f2=f1.copyfun(f1,false)f1.push(4)console.log(f1,f2)
十. 函数
1.定义:
完成某一功能的语句,接收0或多个参数,执行函数体完成某个功能,最后返回处理结果
2.基础语法:
function 函数名(参数){函数体return 结果}
3.函数的定义方式
(1)普通函数
//function student()
function f1(参数【可为空】){ 语句体:var a=10var b=10*2return b
}函数调用:var result=f1() 20
(2) 函数表达式
var f1=function(){函数体
}函数调用:var result=f1() 20
(3) 立即执行函数(匿名函数)
(function(){alert("world")})()
(function(a){alert(Math.pow(a,2))
})(19)
(4) 函数对象创建
var f1=new Function(前面为参数,最后一个为函数体及返回值) 参数可以有很多个
var f1=new Function("alert(23)")f1()var f1=new Function("alert(23)")f1() //23var f1=new Function("a","alert(a*10)")f1(3) //30var f1=new Function("a","return a*10")var c=f1(3)console.log(c) //30var f1=new Function("a","b","c","return a+b+c")var c=f1(3,4,5)console.log(c) //12var f1=new Function("a","b","c=a*b;return c")var d=f1(3,4)console.log(d) //12
4.函数的参数与返回值
(1)普通函数
function f1(a,b){ //形参return a+b
}
f1(2,3) //实参
(2)ES6函数参数
默认参数 :默认参数可以有多个,但必须放在形参末尾
function f1(b=4,m=12,a){return a+b+m}var c= f1(2) console.log(c) //NaN
function f1(a,b){console.log(a,b) if(b==undefined)b=0;//只有一句可以省略{}return a+b}var c=f1(2) //2 undefinedconsole.log(c) //2
不定参数 …
function f1(a,b,c){m=a+b+creturn m}f1(2,3,4)console.log(m) //9
function f1(...arg){//m=a+b+cvar sum=0var n=arg.map((item)=>{return sum+=item})return sum}var result=f1(2,3,4)console.log(result)
参数管理器 arguments
arguments:不知数组,但可以按数组的方式用
可以用数组的形式调实参值
function f1(){console.log(arguments.length) //4console.log(arguments instanceof Array) //falseconsole.log(arguments instanceof Object) //true}f1(2,3,4,5)
function f1(){var n=0for(var i in arguments){n+=arguments[i]}console.log(n)//reduce --不允许使用}f1(2,3,4,5)
形参—函数名.length
function f1(a,b){// arguments[0]// arguments.length //实参的长度console.log(f1.length) //2形参长度}f1(2,3)//形参与实参个数相同的判断arguments.length==f1.length
(5)返回值 —只能有一个
1. 多个参数可返回数组
function f1(a,b){c=a+bd=a-breturn [c,d]}f1(2,3)
2.函数套函数
function f1(a,b){function f2(){return a+b}return f2}var resault=f1(2,3)()console.log(resault)function f1(){}
3.返回函数自身
var a=1function f1(){a++return f1}f1(1)()()()console.log(a)
5.声明变量
1.var 定义变量
var + 变量名
(1)函数体外声明的变量—全局变量【体外体内都可以使用】
var x=5function f1(){alert(x) //5}f1()alert(x) //5
(2) 函数体内定义的变量—局部变量
function f1(){var y=5alert(y) //5}f1()alert(y) //报错
(3)没有var,直接声明变量会进行—隐式声明全局变量
x=5function f1(){alert(x) //5y=6 【这里写var就是局部,不写var变量变成全局变量】}f1()alert(x) //5alert(y) //6
(4)window对象声明全局
function f1(){var y=6window.x=5 //【等同于x=5】}f1()alert(x) //5
显示与隐式全局的区别
var v1="a"v2="b"window.v4="d";(function(){v3="c"})()console.log(delete v1) //false var定义的全局变量不能被删除console.log(delete v2) //true 没经过var定义的全局变量,无论是函数体内还是函数体外都可被删除console.log(delete v3) //trueconsole.log(delete v4) //true
// var定义的全局变量不能被删除没经过var定义的全局变量,无论是函数体内还是函数体外都可被删除
2、变量提升
将变量提升到函数的top位置,只能提升变量的声明,不会提升赋值
(1)
x=1function f1(){alert(x) //undefined***var x=2 //出现重名 预编译var xalert(x) //2var y=5alert(y) //5// 如函数内部要访问全局,采用window.x或window['x']alert(window.x) //1 或alert(window['x']) //1}f1()
(2)
x=1;(function(g){alert(x) //undefinedalert(g.x)//1 alert(window.x)不想明文可使用alert(g.x)var x=2})(window)
3.变量提升—全局作用域
预编译–变量提升
(1)
//var i//var m//var kfor(var i=0;i<3;i++){console.log(i,m,k) //0 undefined undefined 【变量提升】 1 3 3 || 2 3 3for(var m=0;m<3;m++){var k=m+1 }console.log(k) //3}
(2) 变形
for(var i=0;i<3;i++){console.log(i,m,k) //报错 预编译K值提不上去for(var m=0;m<3;m++){k=m+1 //k为隐式的全局变量,没有变量提升}console.log(k) }
(4) 异步情况下变量传递
console.log(1)//异步函数 延迟时间后再输出,所以2最后输出setTimeout(function(){console.log(2)},100)console.log(3) //1 3 2for(var i;i<3;i++){setTimeout(function(){console.log(i)},100)} // 3 3 3 异步调用 ,循环结束
解决:立即执行函数
for(var i=0;i<3;i++){setTimeout((function(m){return function(){console.log(m)}})(i),100)} //0 1 2
6、作用域
1.ES5----函数作用域【函数控制代码块】
function f1(){var y=5alert(y) //5}f1()alert(y) //报错
2.ES5----全局作用域
for(var i=0;i<3;i++){console.log(i,m,k) //0 undefined undefined 【变量提升】 1 3 3 || 2 3 3for(var m=0;m<3;m++){var k=m+1 //3}console.log(k)}
3.ES6—新增 块级作用域
{ },if,for中的{}都属于块级作用域
//(1){var a=1;console.log(a) //1}//(2)if(true){var a=2}console.log(a) //2//(3)for(i=0;i<4;i++){var d=10}console.log(i) //4 for循环外部能访问---渗透console.log(d) //10
变形:
{var a=1;console.log(a) //1let b=2console.log(b) //2}console.log(a) //1console.log(b) //报错if(true){var a=2let b=3}console.log(a) //2console.log(b) //报错for(let i=0;i<4;i++){let d=10}console.log(i) //报错console.log(d) //报错function f1(){let b=2var a=1}f1()console.log(a) //报错console.log(b) //报错
7、setTimeout与setInterval
setTimeout:定时器 指定时间后执行 【主线程完成】
var timmer=setTimeout(csh, 3000);function csh() {console.log('javascript')}clearTimeout(timmer)//清除定时器
setInterval:间歇调用,每隔一定时间调用内容
var timmer=setInterval(csh, 3000);function csh() {console.log('javascript')}clearInterval(timmer)//清除定时器
setTimeout和setInterval都属于JS中的定时器,可以规定延迟时间再执行某个操作,不同的是setTimeout在规定时间后执行完某个操作就停止了,而setInterval则可以一直循环下去
8、var let const区别
ES6新增----
var 对函数作用域有效,对块级作用域无效
允许一个变量声明多次
可以进行变量提升(暂时性死区)
声明的变量会成为window对象的属性window.a
for循环中的迭代变量(var i),var声明会渗透到循环体外
let 对函数作用域和块级作用域都有效
不允许一个变量声明多次
不可以进行变量提升(暂时性死区)
声明的变量不会成为window对象的属性
for循环中的迭代变量(let i),let声明不会渗透到循环体外
const 定义常量
不允许修改–特殊:const定义的引用类型仅保证不发生改变,
块级作用域,函数作用域都有效
不允许重复定义变量
(1)
var avar alet blet b //报错 不允许出现冗余声明(不允许一个变量声明多次)
(2)
var a=5let a=6console.log(a) //报错 不允许出现冗余声明(不允许一个变量声明多次)
(3)
function f1(){alert(a) //undefinedvar a=1alert(b)let b=1 //报错 不可以进行变量提升(暂时性死区)
}
f1()
(4)
var a=5alert(window.a) //5let b=6alert(window.b) //undefined 声明的变量不会成为window对象的属性
(5)
for(var i=0;i<5;i++){}console.log(i) //5for(let i=0;i<5;i++){}console.log(i) //报错 for循环中的迭代变量(let i),let声明不会渗透到循环体外
const举例
(1)
{const a=5a=6console.log(a) //报错}// console.log(a) //报错 不允许更改
(2)
function f1(){const a=5}console.log(a) //报错 ***块级作用域有效,函数作用域有效
(3)
const p1={"name":"zs","age":23}p1.name="ls"console.log(p1) //ls 不允许修改 --特殊:const定义的引用类型仅保证指针不发生改变 ,内容允许被修改
const p1={"name":"zs","age":23}// p1.name="ls"p1={} //报错 改变地址console.log(p1) //ls
9、this
this是js的一个关键字
1.函数的应用——普通函数调用,this指向window,没有意义
function f1(){ //this-->windowthis.x=1alert(this.x) //1}f1()var x=1function f1(){alert(this.x) //1}f1()
2.对象调用——this执行当前的调用对象
function f1(){// alert("hello")alert(this.x) //指向当前对象 【谁调指向谁】}var ol={}ol.x=2ol.method1=f1ol.method1()
3.window == this
this是指向调用值所在函数所绑定的对象浏览器中,不是函数内的this指向的是window
console.log(window==this) //truefunction f1(){x=1}f1()// alert(this.x) //1alert(window.x) //1
var x=1function f1(){console.log(this) //consoel.log(this.x) }var obj1={}obj1.x=2obj1.m1=f1obj1.m1()
var obj1={x:1,m1:function(n){this.x=n},m2:function(){return this.x} } obj1.m1(2)console.log(obj1.m2()) //2 this.x=n -->this指向x改根本上的数,全局作用域变成x=2obj1.m1(3)console.log(obj1.m2()) //3
4. this与DOM元素
(1)this——div DOM元素
<div onclick="console.log(this)">确定</div>
(2)
<div onclick="" id="id01" title="abc" a1="123">q</div>window.onload=function(){function f1(){console.log(this.id)}document.getElementById("id01").onclick=function(){console.log(this) //divconsole.log(this.id) //id01console.log(this.title) //// f1() //f1函数内部的this指向window}
}
3.this整理
1.如在全局范围内使用this,this为当前的window对象
console.log(window==this)window.alert(12)this.alert(12)
2.如是纯粹的函数,this指向window
var x=1function f1(){console.log(this) //windowconsole.log(this.x) //1}f1()
3.如函数中使用this,this代表什么是根据运行此函数在什么对象被调用 即函数中的this指向是在运行时决定的
var x=1function f1(){console.log(this) //{x=2,m1=f}console.log(this.x) //2}var obj1={};obj1.x=2obj1.m1=f1 //绑定对象,让对象去调用obj1.m1()
4.this与DOM元素
this表示指向当前对象
(1)指向dom元素本身
<div onclick="console.log(this)">确定</div><div onclick="this.style.color='red'">确定</div> //点击变红
(2)直接用f1
<div onclick="f1()">确定</div>function f1(){console.log(this) //windowthis.style.color='red' //报错 因为window里没有color属性// alert("a")}
(3)加个事件源:event参数
<div onclick="f1(event)">确定</div>function f1(event){// console.log(event.srcElement)//事件源--调用函数的dom对象event.srcElement.style.color='red'}
(4)
<div id="id01">确定</div>window.onload=function(){document.getElementById("id01").onclick=function(){console.log(this) //this.style.color='red' }}
(5)应用var x=1var obj1={x:2,m1:function(){console.log(this.x) //2}}obj1.m1()var x=1var obj1={x:2,m1:function(){function m2(){console.log(this.x) //1}return m2} }console.log(obj1.m1()) //m2obj1.m1()() //m2--this--window指向obj1var x=1var obj1={x:2,m1:function(){var that=thisfunction m2(){console.log(that) //{x: 2, m1: ƒ}console.log(that.x) //2}return m2} }obj1.m1()()
6.改变this指针----call apply
var x=1
function f1(){console.log(this.x) //obj 2
}
var obj={}
obj.x=2
obj.m=f1
obj.m()
//指向windowvar x=1function f1(){console.log(this.x) // 2}var obj={}obj.x=2// obj.m=f1f1.apply(window) //1f1.apply(obj) //2 没必要obj.m=f1// obj.m()
4.call和apply
1.本质将特定函数当作一个方法绑定到指定对象上进行调用
2.语法 函数.apply(对象,[参数1,参数2。。。]) 函数.call(对象,参数1,参数2。。。)参数—传递给函数的参数【传递的参数传递方式不同】
function f1(x,y){return x+y}var obj={}v1=f1.call(obj,3,4) // 等价于:obj.m1=f1【把obj函数绑定到m1上】// obj.m1(3,4)// delete obj.m1console.log(v1) //7
function f1(x,y){return x+y
}
var obj={}
v1=f1.apply(obj,[3,4])
// 等价于:obj.m1=f1【把obj函数绑定到m1上】// obj.m1(3,4)// delete obj.m1console.log(v1) //7
3.call,apply目的运行函数,用完后马上删除,避免资源的浪费
4.call,apply可以改变this指向
var x=1function f1(){console.log(this.x)//2}var obj={}var x=1function f1(){console.log(this.x)//2}var obj={}obj.x=2f1.apply(obj) //
(2)
function f1(){}var obj={}f1.call(obj)obj.f1() //报错,call调用完立即删除了
(3)
window.color="red"var obj={color:"blue"}function saycolor(){console.log(this.color)}// saycolor()saycolor.call(this) //redsaycolor.call(window) //redsaycolor.call(obj) //blue
5.面向对象
function Person(name,age){console.log("P---",this)this.name1=namethis.age1=age}function Student(name,age,grade){console.log("s---",this)this.grade1=gradereturn Person.apply(this,arguments)}Student()var s1=new Student("hyw",22,3)console.log(s1)
6.bind–就是call与apply的升级版 【扩大函数作用域】
返回函数本身,需要再执行color="red"var obj={color:"blue"}function saycolor(){console.log(this.color)}var v1=saycolor.bind(obj)// console.log(v1) //v1() //blue
7.ES6箭头函数(arrow function)和this
箭头函数定义在哪,this就指向哪
var obj1={"name":"zs","f1":function(){[23,34].map((item)=>{console.log(this) //指向obj})}}obj1.f1()var obj1={"name":"zs","f1":function(){[23,34].map(function(item){console.log(this) //指向window})}}obj1.f1()
十一.闭包
1. 定义
有权访问另一个函数作用域中断变量的函数 缺点:闭包比其他函数占用更多内存,不以过量使用
2. 闭包有哪些
(1) 通过作用域链在全局环境中查找变量x,f1就是闭包
var x=1
function f1(){alert(x)
}
f1()
(2)嵌套在f1中的f2就是闭包
即访问上层函数的作用域的内层函数就是闭包
function f1(){var x=1function f2(){alert(x) //f2是闭包}f2()}
(3) f2在f1函数作用域中声明,在全局作用域中被调用,f2就是闭包
即指在函数声明时的作用域以外的地方被调用的函数需要通过将该函数作为返回值或参数传递,叫闭包
function f1(){var x=1function f2(){alert(x) }return f2}f1()()//参数传递function f1(){var x=1function f2(){alert(x) }f3(f2)}function f3(n){n()} f1() //1 作为参数传递,f2为闭包
3.闭包特性
(1)自闭特性:
闭包内部声明的变量外部无法访问,除非闭包主动向外界提供访问接口
var x=1function f1(){alert(x)var a=2}f1()alert(a) //报错
(2)包裹特性【占用内存】
- 普通函数调用完毕,系统会自动注销函数,释放资源
- 当外部函数被调用后,闭包结构依然被保存在系统中,从而实现包裹数据的目的
function f1(a){var x=avar y=function f2(){return x}return y}var c=f1(1)()console.log(c)
4.闭包应用
(1)使用闭包,能够跟踪动态环境中数据的实时变化
function f1(){var a=1var b=function f2(){return a}a++return b}var c=f1()()alert(c) //2
function f1(){var a=1var b=function f2(){return a}a++a=a+10 //2+10return b}var c=f1()()alert(c) //12 实时返回
(2)闭包不会因为外部环境的注销而消失
当f1执行完毕,并没有被销毁,因为闭包引用了变量a,而继续存在
function f1(){var a=1b=function(){alert(a)}c=function(){alert(a++)}e=function(){alert(a)}d=function(x){alert(a=x)}b() //1c() //1e() //2d(5) //5}f1()
5.闭包的底层原理
(1) 作用域链
1.当某个函数被调用时,会创建一个执行环境和一个相应的作用域链,同时初始化函数的活动对象
2.在作用域链中,该函数处于第一层,函数的外部函数处于第二层,外部的外部处于第三层,直到作用域的终点被称为全局作用域环境.
3.作用域的查找是由低到高,逐级查找
由图可知:
1.匿名函数可以使用f1的所有变量
2.f1执行完毕后,其他活动对象不会被销毁
因为匿名函数的作用域链仍在引用这个活动对象
3.f1=null通知GC-垃圾回收历程将其清除,
作用域,全局作用域一并删除
(2) 闭包重点
<div>aaaa</div>
<div>bbbb</div>
<div>cccc</div>
<script>function f1(){var arr=document.getElementsByTagName("div")for(var i=0;i<arr.length;i++){arr[i].onclick=function(){alert(i)}}}f1()
6. js代码运行机制
1.js是描述性的语言,不需要编译成中间语言, 是由浏览器动态解析与执行
2.js是按<script>代码块分割,进行编译和执行 代码块直接互相独立,变量和方法共享
<script>alert(a) //报错alert("代码块一")var b=1</script><script>alert("代码块二")alert(b) //undefined</script>
3.浏览器对每个代码块进行独立的扫描,在对全局的代码块进行"顺序"执行 在一个块中函数可以在调用之后在进行定义在两个块中,定义函数所在的块必须在函数被调用的块儿之前
<script>alert("代码块一")var b=1function f1(){alert("hello")}</script><script>alert("代码块二")alert(b)f1() //代码块一 代码块二 1 hello</script>
<script>f1() //报错 f1未定义</script><script>function f1(){alert("hello")} //两个块中,定义函数所在的块必须在函数被调用的块儿之前</script>
<script>f1() //hellofunction f1(){alert("hello")}</script>
<script>f1() //函数2function f1(){alert("函数1")}function f1(){alert("函数2")} //js顺序执行:执行到函数1,函数1变量提升,执行到函数2,变量提升,覆盖了函数1。</script>
十二.面向对象
创建方式
对象——属性、方法
1.面向对象创建方式
(1) 普通方式 new Object()
var obj=new Object()//添加对象属性obj.a=12obj.b="hello"//添加对象方法obj.m1=function(){alert("m1...")}obj.m2=function(){alert("m1...")}console.log(obj) //Object { a: 12, b: "hello", m1: m1(), m2: m2() }
var obj=new Object()//添加对象属性obj.a=12obj.b="hello"//添加对象方法obj.m1=function(){alert("m1..."+this.a)} //闭包调外部元素得this指向,否则单纯的a是调不了的obj.m2=function(){alert("m1...")}console.log(obj)//对象的调用console.log(obj.a)console.log(obj.m1)
var obj=new Object()//添加对象属性obj.a=12obj.b="hello"//添加对象方法obj.m1=function(){alert("m1..."+this.a)} //必须this指向否则无法调用obj.m1() //调用函数
var obj=new Object()//添加对象属性obj.a=12obj.b="hello"//添加对象方法obj.m1=function(){console.log(this)alert("m1..."+this.a)}obj.m2=function(){alert("m1...")}console.log(obj)//对象的调用obj.m1()
(2) 直接量方式 var obj1={ }
var obj1={a:12,b:"hello",m1:function(){return("m1..."+this.a)},m2:function(){alert("m1...")}}console.log(obj1)console.log(obj1.m1()) //undefined
(3) 函数对象方法 new Function( )
1.函数
function f1(a,b){return a+b}//转换var f1=new Function('a','b',"alert(a+b)")f1( ,) //有数传进去,不需要this指向
- 对象
var obj=new Function('this.a=12;this.b="hello";this.m1=function(){alert("m1..")};this.m2=function(){alert("m2..")}')//调用var o1=new obj()console.log(o1.a) //用this的方式可以调用方法中的属性值,o1.m2()
(4) 构造函数方式function Person ( ) { this.=}
function Person(){this.name = "zs"this.age = 23this.say = function(){alert("hello")}this.eat = function(){alert("ganguoji...")}}// var a=new Person()// a.say()var hyw1 = new Person()console.log(hyw1.name)hyw1.eat()var hyw2 = new Person()console.log(hyw2.age)hyw2.eat()
(5) 原型方式创建 function Person(){Person.prototype.=}
function Person(){Person.prototype.name="zs"Person.protype.age=23Person.prototype.say=function(){alert("hello...")}Person.prototype.eat=function(){alert("ganguoji")}}//创建实例var p1=new Person()p1.agep1.eat()
2.构造函数–扩展
(1)
function Person(){this.name="zs"this.say=function(){alert("I am "+this.name)}}var p1=new Person() //创建实例化对象【将函数框架转化为具体的】console.log(p1) //Person {name: 'zs', say: ƒ}
function Person(){this.name="zs"this.say=function(){alert("I am "+this.name)}}var p1=new Person()console.log(p1.say())console.log(p1) //{ name: "zs", say: say() }
(2)
function Person(name,age){this.name=name //this.age=agethis.say=function(){alert("I am "+this.name+","+"今年"+this.age)}}var p1=new Person("网红李柯锋",22)p1.say()//{ name: "网红李柯锋", age: 22, say: say() }
(3)构造函数与普通函数区别
1.构造函数最好是大写字母开头
2.构造函数没有ruturn语句
3.构造函数创建实例必须用new
(4)constructor
p1\p2是person对象的不同实例
每个实例都有constructor属性,这个属性指向对象本身
function Person(name,age){this.name=namethis.age=agethis.say=function(){alert("I am "+this.name+"我今年"+this.age+"岁了")}}var p1=new Person("网红李柯锋",22)// console.log(p1)console.log(p1.constructor) //输出函数p1.say()var p2=new Person("李柯凤",3)console.log(p2)
(5)构造函数的问题
构造函数的每一个方法都要在每个实例中创建一遍——导致浪费内存空间
function Person(name,age){this.name=name //this.age=agethis.say=function(){alert("I am "+this.name+","+"今年"+this.age)}}var p1=new Person("网红李柯锋",22)var p2=new Person("李柯凤",3)console.log(p1.say==p2.say) //false
function Person(name,age){this.name=name //this.age=age}
var say=function(){alert("I am "+this.name+","+"今年"+this.age)}var p1=new Person("网红李柯锋",22)console.log(p1.say()) //报错var p2=new Person("李柯凤",3)console.log(p1.say==p2.say) //true 因为都没找着(undefined)----没有根本上解决
3、原型–扩展
特性1:
每一个函数都有一个原型属性,该属性都会指向一个对象,对象中包含所有实例共享的属性和方法
function Person(){Person.prototype.name="zs"Person.prototype.say=function(){alert("I am "+this.name)}}//创建实例var p1=new Person()console.log(p1.name)p1.say()var p2=new Person()console.log(p1.say==p2.say) //true
特性2:hasOwnProperty()
hasOwnProperty():检测一个属性是否在实例中,在返回true,不在返回false
alert(p1.hasOwnProperty("name")) //false 检测来自于实例还是原型alert(p2.hasOwnProperty("name")) //true
function Person(){Person.prototype.name="zs"Person.prototype.say=function(){alert("I am "+this.name)}}var p1=new Person()console.log(p1.name)console.log(p2.name)var p2=new Person()p2.name="ls"console.log(p1.name) //zs name来自于原型的属性console.log(p2.name) //ls name来自于实例的属性alert(p1.hasOwnProperty("name")) //false 检测来自于实例还是原型alert(p2.hasOwnProperty("name")) //truealert("name" in p1) //truealert("name" in p2) //true
特性3——in 操作符:
只要通过对象能够访问到的属性,返回true
console.log("name" in p1) //trueconsole.log("name" in p2) //true
//创建函数,判断是否为原型属性hasPrototypeProperty(p1,"name")
特性4
访问原型的name
p2.name="ls"delete p2.name //zsalert(p2.name)
特性5:
Object.keys() //返回对象定义的属性和方法//官方:列举出所有可枚举(可用for in 遍历)的属性和方法Object.getOwnPropertyNames():无论是否为枚举类型都会列出Object.keys(Person.prototype) //[ "name", "say" ]Object.getOwnPropertyNames(Person.prototype) //[ "constructor", "name", "say" ]
特性6:
优化原型写法
function Person(){Person.prototype.name="zs"Person.prototype.say=function(){alert("I am "+this.name)}}//优化1:function Person(){}Person.prototype.name="zs"Person.prototype.say=function(){alert("I am "+this.name)}//优化2:function Person(){}Person.prototype={constructor:Person, //默认指向object,我需要重新指向name:"zs",say:function(){alert("I am "+this.name)}}var p1=new Person() //objectconsole.log(p1)// p1.say()// var p2=new Person()// console.log(p2.name)function Person(){}Person.prototype={name="zs",say=function(){alert("I am "+this.name)}}
特性7:
(1)原型模式省略了构造函数传递参数的环节
所以所有实例默认情况下,都会取得相同的值
function Person(){}Person.prototype={constructor:Person, //默认指向object,我需要重新指向name:"zs",say:function(){alert("I am "+this.name)}}var p1=new Person() //objectconsole.log(p1)p1.name //zs 缺陷不能往里传值// p1.say()// var p2=new Person()p2.name //zs// console.log(p2.name)
(2)原型属性被实例共享,如对引用类型属性修改,所有实例可能会出现问题
function Person(){}Person.prototype={constructor:Person, //默认指向object,我需要重新指向name:"zs",friends:["lkf","ly","lyg"],say:function(){alert("I am "+this.name)}}var p1=new Person()p1.friends.push("wee")console.log(p1.friends)var p2=new Person()console.log(p2.friends)
4、组合构造函数模式与原型模式
function Person(name,age){this.name=name,this.age=age,this.friends=["aa","bb"]}Person.prototype={constructor:Person,sex:"man",say:function(){alert(this.name+","+this.age+","+this.sex+","+this.friends)}}var p1=new Person("lkf",22)p1.friends.push("ly")p1.say()var p2=new Person("whlkf",12)p2.say()
继承
【vue原理底层】
vue—MVVM
一、对象属性设置–defineProperty
1、Object.getOwnPropertyDescriptor()获取对象属性
var Person={name:"zs"}var des=Object.getOwnPropertyDescriptor(Person,"name")console.log(des.value) //zsconsole.log(des.configurable) //trueconsole.log(des.writable) //trueconsole.log(des.enumerable) //true
2. 对象的数据属性
value 属性的属性值configurable 能否删除属性的值writable 能否修改属性的值enumerable 能否遍历(枚举)属性的值
(1)var Person={}定义空,默认不可删除属性的值,修改属性的值,遍历(枚举)属性的值
var Person={}Object.defineProperty(Person,"name",{value:"zs"})var des=Object.getOwnPropertyDescriptor(Person,"name")console.log(des.value) //zsconsole.log(des.configurable) //falseconsole.log(des.writable) //falseconsole.log(des.enumerable) //false
(2)允许修改
var Person={}Object.defineProperty(Person,"name",{value:"zs",writable:true}) //自定义属性 ---允许修改console.log(Person.name)console.log(Person.name="ls") //没有修改成功console.log(Person.name)
(3)可遍历
Object.defineProperty(Person,"age",{value:"23",enumerable:true}
var v1=Object.keys(Person)
console.log(v1)var Person={}Object.defineProperty(Person,"name",{value:"zs",configurable:true})Object.defineProperty(Person,"age",{value:23,configurable:false})delete Person.name // delete(Person.name)console.log(Person.name) // //添加值//undefinedPerson.name="ls" //添加值console.log(Person.name)delete Person.ageconsole.log(Person.age)
(4)对象的访问属性
get:在读取属性时调用的函数set:在写入属性时调用的函数
var Person={"name":"ze"}Object.defineProperty(Person,"name",{get:function(){console.log("get....")return this.name}
})console.log(Person.name)
var Person={"_name":"ze","age":23} //代表私有var v1=""Object.defineProperty(Person,"name",{get:function(){console.log("get....")return this._name},set:function(val){console.log("set...",val)if(val=="ls"){v1="he is "+valthis.age=55}}
})// console.log(Person._name) //只有zsPerson.name="ls"// console.log(Person.name) //console.log(v1,Person.age)
二、js继承
1、约定
function Person(){var name="zs" //私有的基本属性var friends=["ls","ww"] //私有的应用类型function f1(){} //私有的函数}function Person(){this.name="zs" //实例的基本属性this.friends=["ls","ww"] //实例的应用类型this.f1=function(){} //实例的函数}function Person(){Person.prototype.name="zs" //原型的基本属性Person.prototype.friends=["ls","ww"] //原型的引用类型Person.prototype.f1=function(){} //原型的函数}
2、原型链继承
创建一个对象,Animal,构造函数+原型的函数
name 引用类型 方法say eat
js继承
function Animal(){this.name="animal"this.friends=['wb','b']this.say=function(){console.log("say...");}}Animal.prototype.eat=function(){console.log("eat...")}function Cat(){}//继承Cat.prototype=new Animal()//实例var c1=new Cat()console.log(c1.name)console.log(c1.say)
function Animal(){this.name="animal"this.friends=['wb','b']this.say=function(){console.log("say...");}}Animal.prototype.eat=function(){console.log("eat...")}function Cat(){}//继承Cat.prototype=new Animal()Cat.prototype.name="cat"//实例var c1=new Cat()c1.name="jfm"console.log(c1.name)console.log(c1.say)c1.friends.push("jfcat01")var c2=new Cat()console.log(c2.name)console.log(c2.friends) //写下构造函数里能看到
总结:
核心:Cat.prototype=new Animal() 拿父类实例充当子类原型对象
原型链查找顺序:先在实例中查找实例对象的构造函数-->实例对象原型-->父类构造函数-->父类原型,
优点:简单易于实现
缺点:原型的引用类型属性是所有实例共享的创建子实例时,无法向父类构造函数传参
3、原型链原理:
function Animal(){}Animal.prototype.name="animal"Animal.prototype.say=function(){console.log("hello")}console.log(Animal)// 指向函数本身console.log(typeof Animal.prototype) //objectconsole.log(Animal.prototype.constructor) // Animal
(1)每个函数都有一个显示的“prototype”属性,该属性指向原型对象
(2)原型对象中的“constructor”属性,指向函数本身
var a1=new Animal()
// console.log(a1)
console.log(a1._proto_) //undefined 内部隐藏属性
console.log(a1.prototype) //undefined
(3)new创建的对象,没有prototype属性
function Animal(){}Animal.prototype.name="animal"Animal.prototype.say=function(){console.log("hello")}var a1=new Animal()// console.log(a1)console.log(a1._proto_) //undefined 内部隐藏属性console.log(a1.prototype) //undefined
function Animal(){5}Animal.prototype.name="animal"Animal.prototype.say=function(){console.log("hello")}//继承function Cat(){}Cat.prototype=new Animal()var c1=new Cat()var c2=new Cat()console.log(c1._proto_==Cat.prototype)console.log(Cat.prototype._proto_==Animal.prototype)console.log(Animal.prototype._proto_==Object.prototype)console.log(c1._proto_._proto_==Animal.prototype)console.log(Object.prototype._proto_==null) //原型链结束
(4)每个对象都与有一个“proto”内部隐藏属性, 指向她所对应的原型对象(chrome–[[]] firfox–<>)
(5)原型链利用原型上一个引用类型继承另一个引用类型的方法 (6)Object.prototype.proto==null //原型链结束
4、(借用)构造函数继承
Animal.call(this,arg) //继承
function Animal(val){this.name=valthis.friends=["a","b"]this.say=function(){cobsole.log("say...")}}function Person(arg){Animal.call(this,arg) //继承}var p1=new Person("zs")console.log(p1.name) //zsp1.friends.push("ww")var p2=new Person("ls")console.log(p2.name) //lsconsole.log(p2.friends) //["a","b"]console.log(p1.say==p2.say) //false总结:核心:借用父类的构造函数来增强子类的实例,完全没用到原型有点:1.解决了子类实例共享父类引用属性的问题2.创建子类时可以向父类构造函数传参缺点:无法实现函数的复用,每个子类实例都持有一个新的function函数,消耗内存
5、组合继承(构造函数+原型链)
—常用
function Animal(val){this.name=valthis.friends=["a","b"]}Animal.prototype.say=function(){console.log("say...")}function Person(arg){Animal.call(this,arg) //继承父类基本属性和引用属性,并保持了传参的特点}Person.prototype=new Animal() //继承父类函数,实现了函数复用var p1=new Person("zs")console.log(p1.name)p1.friends.push("dvg")var p2=new Person("ls")console.log(p2.name)console.log(p2.friends)console.log(p1.say==p2.say)核心:把实例函数都放在原型对象上,以实现函数复用,并保留构造函数的优点优点:1、不存在引用类型属性共享问题2、可传参3、函数可复用缺点:1、因为父类的构造函数被调用了两次,生成了两份,浪费内存
6.原型式继承(了解)
function Beget(obj){ //生孩子函数function F(){}F.prototype=objreturn new F()}function Animal(){this.name="animal"this.friends=["ls","ww"]}var Person=new Animal()var p1=Beget(Person)console.log(p1.name) //animalp1.name="zs"p1.friends.push("zl")var p2=Beget(Person)console.log(p2.name) //animalconsole.log(p2.friends) //["ls","ww","zl"]核心:用生孩子函数得到一个“纯洁”的(没有实例属性)的新对象
7.寄生式继承
function Beget(obj){ //生孩子函数function F(){}F.prototype=objreturn new F()}function Animal(){this.name="animal"this.friends=["ls","ww"]}function getSubject(obj){var clone=Beget(obj)clone.age=23return clone}var Person=getSubject(new Animal())console.log(Person.name) //animalconsole.log(Person.age)
8.寄生组合式继承—最佳
function Beget(obj){ //生孩子函数function F(){}F.prototype=objreturn new F()}function Animal(){this.name="Animal"this.friends=["ls","ww"]}Animal.prototype.say=function(){console.log("say...")}function Person(){Animal.call(this)}//核心代码 --切掉了原型对象上多余的那份父类实例属性var p=Beget(Animal.prototype)p.constructor=PersonPerson.prototype=pvar p1=new Person()console.log(p1.name) //Animalconsole.log(p1.friends) //["ls","ww"]优点:完美
缺点:没有
十三. BOM编程
browser object model 浏览器对象模型
window--|--document|--navigator|--history|--location|--screen|--frames
1、window对象
1.对话框
(1)alert() 消息提示框window.alert("hello") //window可以省略(2)prompt() 消息输入框(3)confirm() 消息确认框var v1=window.confirm("确定删除吗")确定 v1--true
2.间歇调用与超时调用
setInterval(): 间歇调用,按照时间间隔执行代码,直到间歇调用取消或页面被卸载
取消间歇调用:clearInterval()
window.setInterval(function(){alert("hello")},1000)var n=0function f1(){n++if(n==5){clearInterval(timmer)}}var timmer=setInterval(f1,1000)
setTimeout():超时调用,指定时间后执行代码
取消超时调用:clearTimeout()
只要指定时间没到,调用该方法,取消超时调用
window.setTimeout(function(){alert("hello")},1000)
3. open打开窗口
window.open(“index.html”)
var w1=window.open("demo.html","新窗口","width=300px,height=221px,scrollbars=yes,screenX=150px,screenY=500px")//scrollbars滚动条
如果w1==null 窗口没弹出 —>窗口被拦截
window.close()关闭窗口
4.窗口滚动
scrollTo 窗口滚动到指定位置 scrollBy 在原位置滚动调整window.scrollTo(0,1000)window.scrollBy(0,100)
滚动条demo
1、setInterval实现
window.scrollTo(0,1000)function f1(){var s=10;time=1n=0var aee=window.setInterval(function(){window.scrollBy(0,s)n++if(n==1000/s){clearInterval(aee)}},time)}<button onclick="f1()">确定</button><div style="width:200px;height:2000px;background-color:red"></div>
2、setTimeout实现
function f1(n){if(n==0){return 1}return setTimeout(function(){window.scrollBy(0,1)f1(n-1)}, 1);}<button onclick="f1()">确定</button><div style="width:200px;height:2000px;background-color:red"></div>
2、history
保存用户上网的历史记录,从窗口打开的那一刻算起
保存用户上网的历史记录,从窗口打开的那一刻算起window.history.back() //前一页==history.back()history.forward() 后一页history.go(-1) 前一个history.go(-2) 前两页 history.go(0) 当前页history.go(1) 后一页
3、location 页面跳转
1、页面跳转功能
window.location.href="demo.html"location.href="demo.html"location.assign("demo.html")window.document.location.href="demo.html"
2、获取url属性
location.host //服务器名及端口号location.hostname //服务器名location.port //端口号location.protocol //使用协议location.pathname //路径location.search //参数
http://127.0.0.1:5501/yu/d16_Bom/index1.html?a=12&b=23location.host //'127.0.0.1:5501' 服务器名称即端口号location.hostname //'127.0.0.1' 服务器名location.port //'5501' 端口号location.proticol //undefined //协议location.pathname //'/yu/d16_Bom/index1.html' 路径location.search //'a=12&b=23' 参数
3.页面重新加载
location.reload() 如果缓存区有就从缓存区里拿,如果没有从服务器上加载location.reload(true) 直接从服务器加载
4.页面替换
location.replace() 跳转页面,不会产生历史记录
4、navigator——浏览器内核处理
1、参数解析
console.log(navigator.userAgent) //用户代理console.log(navigator.appName) //Netscapeconsole.log(navigator.appCodeName) //浏览器代码名称console.log(navigator.appVersion) //浏览器版本console.log(navigator.platform) //win32 操作系统 mac--苹果 linux--linux操作系统 x11--unix操作系统console.log(navigator.mimeType) //获取浏览器资源媒体类型----一般指插件 返回数组
2、浏览器内核
定义: 浏览器内核也叫排版引擎,也叫渲染引擎,主要功能获取网页内容(html,图像等),整理信息(加入css等) 计算网页的显示方式,输出到显示器或其他媒介上
(1)webkit 苹果的开源内核 safari chormejs引擎 safari--Nitrochorme--v8html引擎 KHTML
(2)blink webkit的一个分支,早期的safari chrome(3)Trident IE内核
(4)Gecko firefox ff内核js引擎 JagerMonkeyhtml引擎 Gecko
(5)persto opera 早期内核
5、screen 客户端显示器信息
screen.width //屏幕的像素宽screen.height //屏幕的像素高screen.availWidth //浏览器窗口所占最大宽度screen.availHeight //浏览器窗口所占最大高度screen.screenTop //浏览器距离顶部的距离window.screenLeft //浏览器距离左面的距离
console.log(v1.offsetWidth) //元素当前可视窗口的宽console.log(v1.offsetHidth) //元素当前可视窗口的高console.log(v1.scrollHeight) //元素实际的高console.log(v1.scrollWidth) //元素实际的宽console.log(v1.offsetLeft) //元素相对于浏览器边界的偏移console.log(v1.offsetTop)
6、iframe
1. 内联框架:在html文件中嵌入另一个文档
<iframe name="if01" src="test02.html"width="300" height="400" frameborder="10"style="border:10px solid red; background-color:yellow"><iframe> //出现一个框
2、iframe框架传参
1、同域
iframe名称.window.子框架函数名(传递内容)
父:
<iframe name="if01" src="test02.html"></iframe><button onclick="f1()">确定</button><script>function f1(){if01.window.subfun("hello my son!")}</script>
子:
function subfun(arg){document.getElementById("show").innerText="父框架传递来的数据:"+arg}<div id="show"></div>
2、跨域
postmessage :可实现跨域通信、
语法:窗口对象.postMessage(消息内容,目标窗口)
(1)父——>子
//发送信息if02.contentwindow.postMessage("hell sub wanghao","http://10.10.255.44:5500")//接收信息window.addEventListener("message",function(event){alert(event.data)})//全局事件监听
十四、DOM编程
DOM—Document Object Model 文档对象模型
<!DOCTYPE html>><html><head><title></title></head><body><div></div><p></p></body></html>
window.onload=function(){console.log(document.childNodes[0]) //声明头console.log(document.childNodes[1]) //声明bodyconsole.log(document.childNodes[1].childNodes[2].childNodes[1]) //查div}//页面按照顺序加载,先加载了script,然后再加载带有id的标签,导致了script无法找到正确的id。window.onload可以让页面加载完毕后再执行里面的代码块。
1、childNodes
childNodes:每个节点都有集合属性,数组对象
—————— 表示该节点的所有节点的集合
注意:***会将元素之间的空格当作文本节点 ***
document.childNodes[0] element.firstchildelement.lastchildelement.parentNode element.nextSibling //相邻节点下一个element.previousSibling //相邻节点上一个
//通过ccc的标签查找ddd aaa,titlewindow.onload=function(){var a=document.childNodes[1].childNodes[2].childNodes[3].childNodes[1]console.log(a)var b=a.nextSibling.nextSiblingconsole.log(b)var c=a.parentNode.parentNode.previousSibling.previousSibling.childNodes[1]console.log(c)}
childNodes.length 长度
2、节点信息
(1) nodeType 节点类型标签节点返回 1文本节点返回 3(2) nodeValue 节点值 元素节点 null文本节点 文本内容(3) hasChildNodes()判断是否有子节点
console.log(document.body.nodeType) //1
nodeType 属性返回以数字值返回指定节点的节点类型
如果节点是元素节点,则 nodeType 属性将返回 1。
如果节点是属性节点,则 nodeType 属性将返回 2。
3、childrens
childrens 返回所有子节点,忽略所有空格和文本节点,注释
只返回元素节点
element.firstElementchildelement.lasttElementchildelement.parenttElementNodeelement.nexttElementSiblingelement.previoustElementSibling
javascript全程笔记相关推荐
- JavaScript基础笔记集合(转)
JavaScript基础笔记集合 JavaScript基础笔记集合 js简介 js是脚本语言.浏览器是逐行的读取代码,而传统编程会在执行前进行编译 js存放的位置 html脚本必须放在< ...
- Java程序猿的JavaScript学习笔记(12——jQuery-扩展选择器)
计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...
- Java程序猿的JavaScript学习笔记(汇总文件夹)
最终完结了,历时半个月. 内容包含: JavaScript面向对象特性分析,JavaScript高手必经之路. jQuery源代码级解析. jQuery EasyUI源代码级解析. Java程序猿的J ...
- JavaScript学习笔记(五)
JavaScript学习笔记(五) ①Array类 本地对象 ②Date类 ①Global对象 对象的类型 内置对象 ②Math对象 宿主对象 今天继续学习JS中的对象,昨天内置对象Global对 ...
- JavaScript学习笔记(备忘录)
JavaScript学习笔记(备忘录) ===运算符 判断数值和类型是否相等.如: console.log('s'==='s') //输出trueconsole.log('1'===1) //输出fa ...
- Java程序猿的JavaScript学习笔记(10—— jQuery-在“类”层面扩展)
计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...
- JavaScript学习笔记(十)——学习心得与经验小结
JavaScript学习笔记(十)--学习心得与经验小结 目前我先列好提纲,利用每晚和周末的闲暇时间,将逐步写完 ^_^ 转载于:https://www.cnblogs.com/mixer/archi ...
- JavaScript 学习笔记(1)
1. 何为 Jscript JScript 是一种解释型的.基于对象的脚本语言. 局限性: 1) 不能使用该语言来编写独立运行的应用程序 2) 没有对读写文件的内置 ...
- 前端获取div里面的标签_web前端教程JavaScript学习笔记DOM
web前端教程JavaScript学习笔记 DOM一DOM(Document Object Model): 文档对象模型 其实就是操作 html 中的标签的一些能力 我们可以操作哪些内容 获取一个元素 ...
最新文章
- PHP 获取数组最后一个值
- Tencent云联网灾备方案
- 应用session对象实现用户登录
- python中try...except的用法_提高开发效率,从避免滥用 try...except... 开始
- 基于RulesEngine的业务规则实现
- java生成pdf加密_java使用iText 生成PDF全攻略(表格,加密)
- 如何计算近似纳什均衡_通证经济系列之纳什均衡
- CSS基础学习-13.CSS 浮动
- HDU 5045 状压DP 上海网赛
- 那些不得不提的坑(持续添加中)
- MED-V服务器配置,MED-V系列之二
- STC学习:按键消抖计数
- DMA内存申请--dma_alloc_coherent 及 寄存器与内存【转】
- 创业维艰,技术人创业如何少走弯路?
- 软考—软件设计师(软件工程基础知识)
- python股票量化交易(13)---使用pyqt5构建股票交易K线形态
- 大数据计算成都峰会—开启西南大数据新洞察
- 史上最牛恶搞小游戏,快快转发,分享这份“快乐”
- Visual Studio Community2015及使用
- 【Renesas RA6M4开发板之UART与Serial studio串口交互】
热门文章
- 联想Y410P:合上盖子用teamviewer远程黑屏问题
- [34期] 一路向北
- SIMcom嵌入式Linux平台通用配置
- 如何将TN系统转化为IT系统?医用隔离电源系统为您解决难题
- rfa 文件读取_【winrfa修改】简单载具的Objects.rfa文件详解
- sketch生成android代码,Android资源、点九图和 XML Sketch导出工具Android Res Export
- UI酷炫!最新开源的Vue3.2移动电商实战(源码+文档分享)
- 同步和异步的区别及优缺点 通俗理解
- python Homework03
- 油井远程监控解决方案