javascript全程笔记

一、js基础

1.内核

谷歌WebKit
IE11Trident
火狐Gecko
safariWebkit
operaWebkit

2.javascript组成

1.ECMA Script :【规定了js的语法,类型,语句,关键字,操作对象等 ES6 2015.6】
2.Dom (document object model ) 文档对象模型
3.Bom (browser object model) 浏览器对象模型

二、数据类型

弱类型语言:变量类型是由它所包含的数据决定的

1.数据类型

		1、typeof() 判断数据类型函数
		2、数值型number
		3、布尔bollean
		3、字符串string
		4、undefined
		5、null
		6、object

2.类型转换

(1)隐式类型转换:
(2)显式类型转换(强制类型转换)

  Number()    		【将其他数据类型转换成数值型】
	  Number("12.23")      //12
	  Number(true)   	   //1 
	  Number(false)        //0
	  Number("")           //0
	  Number("null")       //0
	  Number("undefined")  //NaN
	  Number("NaN")        //NaN
  parseInt()
        console.log(parseInt("hello"))          //NaN
        console.log(parseInt("23aa"))           //23
        console.log(parseInt(12.23))            //12
        console.log(parseInt(0.12))             //0
        console.log(parseInt(true))             //NaN
        console.log(parseInt(false))            //NaN
        console.log(parseInt(""))               //NaN
        console.log(parseInt(25,16))            //37    16进制数,输出10进制
        console.log(parseInt(25,8))             //21
        console.log(parseInt(1001,2))           //***9
        console.log(parseInt(25,10))            //25        				   

NaN:not a Number 非数值【一个本来要返回数值的操作数,而没有返回数值的情况】

 parseFlot()
	  console.log(parseFloat("23.34"))        //23.34
	  console.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))    //false
          console.log(isFinite(200e5))      //true
   isNaN()   //判断是否为非数值
        console.log(isNaN("hello"))     //true
        console.log(isNaN(true))        //false
        console.log(isNaN(false))       //false
        console.log(isNaN("10"))         //false

(1)任何涉及NaN的操作,都返回NaN

	console.log(NaN/8)  //NaN
    console.log(NaN+8)  //NaN
    console.log(NaN-8)  //NaN
    console.log(NaN*8)  //NaN

(2)NaN与任何值都不相等,包括t他本身NaN

	NaN==NaN        //false
	0/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))            //true
  console.log(Boolean(0))             //false
  console.log(Boolean("hello"))       //true
  console.log(Boolean(""))            //false
  console.log(Boolean(null))          //false
  console.log(Boolean(undefined))     //false
                 true      false
    数值型         非空       0
    字符型         非空串     " "
    undefined     返回false
    null          返回false
    object        任意对象返回都是true

7. undefined类型

1、 变量只声明,未赋值

   var a;
    console.log(typeof(a))  //undefined
    alert(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 循环 至少执行一次
6break    立即跳出循环
7continue 停止当前循环,进入下一次循环

四、字符串操作

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 wor
    console.log(s1.substr(0))           //hello world
    console.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 world
        console.log(s1.substring(3,7))           //lo w
        console.log(s1.substring(0))           //hello world
        console.log(s1.substring(-3))           //hello world   负数转为0
        console.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 world
		console.log(s1.slice(3,6))           //lo 
		console.log(s1.slice(0))           //hello world
		console.log(s1.slice(-3))           //rld
		console.log(s1.slice(3,-4))           //lo w    3到-4
		console.log(s1.slice(8,3))           //
(4)字符串大小写转换

s1.toLowerCase() 小写
s1.toUpperCase() 大写

        var s2="fdhvfdhDD"
        console.log(s2.toLowerCase())  //fdhvfdhdd
        console.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") )   //1
    console.log(s1.indexOf("o"))    //4
    console.log(s1.indexOf("m"))    //-1
    console.log(s1.indexOf("o",6))  //7
	s1.lastIndexOf("o")			//7
	s1.lastIndexOf("l")			//9
	
	var s1="hello world"
	console.log(s1.lastIndexOf("e") )   //1
(8)replace替换

1)返回新字符串
2)只替换第一个匹配项

   s1="hello"
   s2=s1.replace("e","m")	//hmllo
   s2=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))      //u6D77
 console.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)      //1
		console.log(a++)     //1
		console.log(a)     //2
		
		var a= 1;
		console.log(a)      //1
		console.log(++a)     //2
		console.log(a)     //2
		// var a=1
		// b=a++ + ++a +a++
		// a=4	****
		// b=7

 		var a= 3;
        var b=a++ + --a+ ++a+a--        //14
        console.log(b)

+

	console.log(0+0)    //0
	console.log(-0+-0)  //-0
	console.log(Infinity+Infinity)  //ininfinity
	console.log(-Infinity+-Infinity)    //-infinity
	console.log(Infinity+Infinity)  //NaN
	var c=false;
    console.log(c++)    //0
    console.log(--c)    //-1

2.赋值运算符

	+=  -=   *=    /=  %=

a=1;
a=a+3   --->a+=3
 var a=12
    b=11
    c=a*=b+5
    c1=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        //true
		a===b       //false
	==代表相同,先检查两个操作数的数据类型,
                发现不同。可进行类型转换,再进行值的比较,
                如果相同,则调用===比较
                null==undefined           //true  都是空

    ===严格相同,如果类型不同,直接判断不同
                类型不同,一定不相等     
                null===undefined        //true
                NaN===NaN       //false 值很多
                console.log(null===null)        //true 按空算【不是转number】
                console.log(undefined===undefined)      //true 按空算【不是转number】
		console.log(NaN==NaN)       //false
		console.log(NaN===NaN)     //false
		console.log(null==0)       //false  
		console.log(undefined==0)     //false
		console.log(true==1)	     //true
		
		console.log("Black">"Mick")     //比较ASCII吗
		console.log("23"<"3")
		console.log("a"<"3")

4.逻辑运算符

&& -------> 都为真才为真,
|| ------>一个为真才为真
! ------>真变假,假变真

短路运算符——js依次获取每一个操作数,将他们转换为布尔变量,如果是false, 则中断后面的处理,返回这个操作数的值,否则继续处理下一个操作数,返回最后操作数的值,以上称为逻辑判断的短路运算在这里插入图片描述

		var a=100
        var b=false
        var c=(b&&(a=25))
        console.log(a)      //100 &&不进行后面运算
        var A="1" && true && 0 && false && "abc"  //A=0 false为假

特殊例子

		console.log(-0+-0)  //-0
		console.log(Infinity+Infinity)  //NaN
		console.log(Infinity*0) //*NaN
		console.log(0/0)    //NaN 0不能做分母
        console.log(Infinity/Infinity)  //NaN
        console.log("m"+1+1)  //m11  
        console.log(1+1+"m")//2m
        console.log("m"+(1+1))//m2

 		var b="001"     //当作1来用
        console.log(b++)    //1
        console.log(b--)    //2****
        console.log(NaN==NaN)       //false
		console.log(NaN===NaN)     //false

5、typeof

 	console.log(typeof(1))      			//number
    console.log(typeof(NaN))    			//number
    console.log(typeof(Number.MAX_VALUE))   //number
    console.log(typeof(Number.MIN_VALUE))   //number
    console.log(typeof(Infinity))    		//number
    console.log(typeof("123"))      		//string
    console.log(typeof(true))       		//boolean
    console.log(typeof(Date))       		//function
    console.log(typeof(c))          		//undefined
    console.log(typeof(undefined))  		//undefined
    console.log(typeof([]))         		//object
    console.log(typeof(Math))       		//object
    console.log(typeof(window))     		//object
    console.log(typeof(document))   		//object
    console.log(typeof(null))       		//object

(1)数值类型 typeof返回number

	console.log(typeof(1))      //number
    console.log(typeof(NaN))    //***number
    console.log(typeof(Number.MAX_VALUE))    //number
    console.log(typeof(Number.MIN_VALUE))    //number
    console.log(typeof(Infinity))    //number

(2)字符串类型,typeof返回 string

 typeof("123")   //string

(3)布尔类型,typeof返回boolean

  typeof(true)    //boolean

(4)对象、数组、null、typeof返回object

	  console.log(typeof([]))         //object
      console.log(typeof(Math))       //object
      console.log(typeof(window))     //object
      console.log(typeof(document))   //object
      console.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)    //3
		011 | 010==>011=>3
		console.log(3^2)    //1
		console.log(~3)     //-4011——>(取反)100——>减一011——>再取返100  变符号位】
		console.log(~25)     //-
11001 00110 00101*** 11010
		console.log(25&3)       //1
		console.log(25|3)       //27
		console.log(25^3)       //26
		console.log(~25)        //-24
		console.log(~(-27))     //26
		console.log(64>>5)      //2
		console.log(255&85)     //85

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.三元(目)运算符

        a=10
        if(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 0
    d1.getMinutes() 分钟 1.59 0
    d1.getMonth()  月 0.11
    d1.getSeconds() 秒 1.59.0
    d1.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/11
    console.log(s1.toLocaleString())   //2022/7/11 23:22:43
    console.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()+1
            var 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+1
        console.log(Math.floor(a))
//(2)返回0-10之间的随机整数
        Math.round(Math.random() * 10)      //0-9
        Math.floor(Math.random()*11)        //0-10【0.99*11=10.89】
//(3)返回指定范围的随机整数
        f1(10,200) 包含10200
       //【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.1
        function 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]) //undefined
    console.log(a1.length)//3

    var a2=[,,,,]   //最后一个逗号忽略,所以按4来提
    console.log(a2[2])  //undefined
    console.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 in
		    for(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) //helloomm
	    console.log(typeof(a2))
	
		a2.join("3") //he3ll3oo3mm
	var a1=[2,3,4] //alert只接收字符串
	    a2=a1.toString()
	    console.log(a2) //2,3,4

(3) concat

  1. 连接数组,将数据加到末尾
  2. 不修改原数组,生成新数组
  3. 只能打散一维数组,不会打散数组中包含的数组
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,89
    0 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) 数组删除

  1. splice()
  2. 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)) //true
        if(a1 instanceof Array){
            console.log(true)
        }//true
        if(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])       //undefined

    console.log(a1[-2])  //undefined
    console.log(a1[2.3])  //undefined 

	4. 下标是可以不断递增的表达式****
	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].name
    data1[1].age
    data1[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].number

    var Maxage=0
    data1.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              1152
0.1
    0.0001 1001 1001 1001....(1100的循环)
0.2
    0.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.2
		a.toFixed(1)  //0.3
(3)第三方库

3.tofixed()的局限性
 var a=1.35
     console.log(a.toFixed(1))  //1.4
     console.log(1.336.toFixed(2)) //1.34
     console.log(1.3335.toFixed(3)) //1.333
4.优化tofixed()

【对toFixed()进行封装】

 //方法1
         Number.prototype.mytoFixed=function(b){
            var a = this.toString()
            var c = (a.substring(0,a.indexOf(".")+1)).length
            var 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.334
        console.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);
}
//方法3
        Number.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)) //string
        console.log(typeof(s2)) //object
   var n=1
        s1=new String(++n,n++,++n)
        console.log(s1)  //2
        console.log(n)  //4
        s2=new String(1,2,3,4)
        console.log(s2)  //1

2、包装类型中的 Boolean

  v1=false
  v2=v1&&true      false
v1 =new Boolean(false)
    v2 =v1&&true
    console.log(v1)  //Boolean { false }  是对象
    console.log(v2)  //true v1强制转换成对象为true

(1)

var v3=false
    v4=new Boolean(false)
    console.log(typeof(v3)) //boolean
    console.log(v4) //Boolean {false}包装对象
    console.log(v3 instanceof Boolean) //false

(2) instanceof 判断是否是对象实例

  v3 instanceof Boolean //false
  v4 instanceof Boolean //true

3. 包装类型的Number

  		var v1=23
        v2=new Number(23) 
        console.log(v1) //23 number
        console.log(v2) //Number
        console.log(v1 instanceof Number) //false
        console.log(v2 instanceof Number) //true 

6.值类型与引用类型

1、值类型

值类型的传递空间大小固定,采用基本数据类型
    string   number   null   undefined

存储在栈内存中,
占据的空间是固定的

2、引用类型

引用类型采用地址传递: 数组(array),函数(function),对象(object)
堆中存储的一般都是对象,通过一个地址编号(也叫引用指针)传递给栈内存的变量

读取数据的时候,由引用指针(地址编号)到堆内存中查找数据块
占据的空间是不固定的

3、 值传递,引用类型传递

  var a=2
        function 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=12
	b=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=a1
    console.log(a1,a2) //数组123
    a1.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,3
    console.log("数组的新值:" + arr2 );    //数组的新值:1,7,3
3.数组方法concat
   var arr1 = [1,2,3];
    var arr2 = arr1.concat();
    arr2[1] = 7;
    console.log("数组的原始值:" + arr1 ); //数组的原始值:1,2,3
    console.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=10
        var b=10*2
        return 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() //23

    var f1=new Function("a","alert(a*10)")
    f1(3) //30

    var f1=new Function("a","return a*10")
    var c=f1(3)
    console.log(c)  //30

    var f1=new Function("a","b","c","return a+b+c")
    var c=f1(3,4,5)
    console.log(c)  //12

    var 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 undefined
	    console.log(c)  //2

不定参数 …

	function f1(a,b,c){
	    m=a+b+c
	    return m
	}f1(2,3,4)
	console.log(m)  //9
function f1(...arg){
             //m=a+b+c
             var sum=0
             var 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)  //4
            console.log(arguments instanceof Array)  //false
            console.log(arguments instanceof Object) //true
        }
        f1(2,3,4,5)
 function f1(){
        var n=0
            for(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+b
            d=a-b
            return [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=1
        function f1(){
            a++
            return f1
        }
        f1(1)()()()
        console.log(a)

5.声明变量

1.var 定义变量

var + 变量名

(1)函数体外声明的变量—全局变量【体外体内都可以使用】
   var x=5
    function f1(){
        alert(x)  //5
    }
    f1()
    alert(x)    //5
(2) 函数体内定义的变量—局部变量
function f1(){
        var y=5
        alert(y)  //5
    }
    f1()
    alert(y)  //报错
(3)没有var,直接声明变量会进行—隐式声明全局变量
    x=5
    function f1(){
        alert(x) //5
        y=6 【这里写var就是局部,不写var变量变成全局变量】
    }
    f1()
    alert(x)  //5
    alert(y)  //6
(4)window对象声明全局
   function f1(){
                var y=6
                window.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)  //true
	console.log(delete v4)  //true
// var定义的全局变量不能被删除
   没经过var定义的全局变量,无论是函数体内还是函数体外都可被删除

2、变量提升

将变量提升到函数的top位置,只能提升变量的声明,不会提升赋值

(1)

	x=1
	function f1(){
	    alert(x) //undefined***
	    var x=2 //出现重名  预编译var x
	    alert(x)  //2
	    var y=5
	    alert(y)  //5
	    // 如函数内部要访问全局,采用window.x或window['x']
	    alert(window.x)  //1 或
	    alert(window['x'])  //1
	}
	f1()

(2)

 	x=1;
        (function(g){
            alert(x)  //undefined
            alert(g.x)//1  alert(window.x)不想明文可使用alert(g.x)
            var x=2
        })(window)

3.变量提升—全局作用域

预编译–变量提升

(1)

   //var i
    //var m
    //var k
    for(var i=0;i<3;i++){
                console.log(i,m,k)  //0 undefined undefined 【变量提升】 1 3 3 ||  2 3 3
                for(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   2

    for(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=5
            alert(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 3
            for(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) //1
            let b=2
            console.log(b)  //2
        }
        console.log(a)   //1
        console.log(b)  //报错


        if(true){
            var a=2
            let b=3
        
        }
        console.log(a) //2
        console.log(b) //报错

        
        for(let i=0;i<4;i++){
            let d=10
        }
        console.log(i)  //报错
        console.log(d)  //报错

        function f1(){
                    let b=2
                    var 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 a
    var a
    let b
    let b  //报错  不允许出现冗余声明(不允许一个变量声明多次)

(2)

  var a=5
    let a=6
    console.log(a)  //报错 不允许出现冗余声明(不允许一个变量声明多次)

(3)

  function f1(){
    alert(a)  //undefined
    var a=1
    alert(b)
    let b=1   //报错  不可以进行变量提升(暂时性死区)
}
f1()

(4)

 var a=5
    alert(window.a) //5
    let b=6
    alert(window.b)  //undefined  声明的变量不会成为window对象的属性

(5)

   for(var i=0;i<5;i++){}
    console.log(i)  //5
    for(let i=0;i<5;i++){}
    console.log(i)  //报错    for循环中的迭代变量(let i),let声明不会渗透到循环体外

const举例

(1)

   {
            const a=5
            a=6
            console.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-->window
        this.x=1
        alert(this.x)  //1
    }
    f1()

    var x=1
    function f1(){
        alert(this.x)  //1
    }f1()

2.对象调用——this执行当前的调用对象

  function f1(){
        // alert("hello")
        alert(this.x)  //指向当前对象  【谁调指向谁】
    }
        var ol={}
        ol.x=2
        ol.method1=f1

        ol.method1() 

3.window == this

this是指向调用值所在函数所绑定的对象浏览器中,不是函数内的this指向的是window

  console.log(window==this)  //true
        function f1(){
            x=1
        }
        f1()
        // alert(this.x)  //1
        alert(window.x)   //1
 var x=1
    function f1(){
        console.log(this)  //
        consoel.log(this.x)  
    }
    var obj1={}
    obj1.x=2
    obj1.m1=f1
    obj1.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=2
    obj1.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)  //div
            console.log(this.id)  //id01
            console.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=1
    function f1(){
        console.log(this)  //window
        console.log(this.x) //1
    }
    f1()

3.如函数中使用this,this代表什么是根据运行此函数在什么对象被调用 即函数中的this指向是在运行时决定的

 var x=1
    function f1(){
        console.log(this)  //{x=2,m1=f}
        console.log(this.x) //2
    }
    var obj1={};
    obj1.x=2
    obj1.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)  //window
                this.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=1
            var obj1={
                x:2,
                m1:function(){
                    console.log(this.x)  //2
                }
            }
            obj1.m1()

            var x=1
            var obj1={
                x:2,
                m1:function(){
                    function m2(){
                        console.log(this.x)  //1
                    }
                    return m2
                } 
            }
            console.log(obj1.m1())  //m2
            obj1.m1()()  //m2--this--window

    指向obj1
            var x=1
            var obj1={
                x:2,
                m1:function(){
                    var that=this
                    function 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()
 //指向window
 var x=1
    function f1(){
        console.log(this.x) // 2
    }
    var obj={}
    obj.x=2
    // obj.m=f1
    f1.apply(window) //1
    f1.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.m1

        console.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.m1

console.log(v1)  //7

3.call,apply目的运行函数,用完后马上删除,避免资源的浪费
4.call,apply可以改变this指向

   var x=1
        function f1(){
            console.log(this.x)//2
        }
        var obj={}

        var x=1
        function f1(){
            console.log(this.x)//2
        }
        var obj={}
        obj.x=2
        f1.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)  //red
    saycolor.call(window)  //red
    saycolor.call(obj)  //blue

5.面向对象

  function Person(name,age){
        console.log("P---",this)
        this.name1=name
        this.age1=age
    }
    function Student(name,age,grade){
        console.log("s---",this)
        this.grade1=grade
        return 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=1
        function f2(){
            alert(x)        //f2是闭包
        }
        f2()
    }

(3) f2在f1函数作用域中声明,在全局作用域中被调用,f2就是闭包
即指在函数声明时的作用域以外的地方被调用的函数需要通过将该函数作为返回值或参数传递,叫闭包

  function f1(){
        var x=1
          function f2(){
                alert(x)       
             }
            return f2
    }
    f1()()
    
    //参数传递
     function f1(){
        var x=1
          function f2(){
                alert(x)       
             }
            f3(f2)
    }
	     function f3(n){
	            n()
	     }	
    f1()   //1    作为参数传递,f2为闭包

3.闭包特性

(1)自闭特性:

闭包内部声明的变量外部无法访问,除非闭包主动向外界提供访问接口

	var x=1
        function f1(){
            alert(x)
            var a=2
        }
        f1()
        alert(a)  //报错

(2)包裹特性【占用内存】

  1. 普通函数调用完毕,系统会自动注销函数,释放资源
  2. 当外部函数被调用后,闭包结构依然被保存在系统中,从而实现包裹数据的目的
function f1(a){
        var x=a
        var y=function f2(){
            return x
         }
    	return y
    }
    var c=f1(1)()
    console.log(c)

4.闭包应用

(1)使用闭包,能够跟踪动态环境中数据的实时变化

	function f1(){
	    var a=1
	    var b=function f2(){
	        return a
	    }
	    a++
	    return b
	}
	var c=f1()()
	alert(c)  //2
   function f1(){
        var a=1
        var b=function f2(){
            return a
        }
        a++
        a=a+10  //2+10
        return b
    }
    var c=f1()()
    alert(c)  //12 实时返回

(2)闭包不会因为外部环境的注销而消失

当f1执行完毕,并没有被销毁,因为闭包引用了变量a,而继续存在

  function f1(){
        var a=1
        b=function(){alert(a)}
        c=function(){alert(a++)}
        e=function(){alert(a)}
        d=function(x){alert(a=x)}
        b() //1
        c() //1 
        e()  //2
        d(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=1
	    function f1(){alert("hello")}
	</script>
	<script>
	    alert("代码块二")
	    alert(b)
	    f1()  //代码块一  代码块二 1 hello
	</script> 
    <script>
        f1()   //报错 f1未定义
    </script>
    <script>
        function f1(){alert("hello")}  
        //两个块中,定义函数所在的块必须在函数被调用的块儿之前                                                     
    </script>
	<script>
	    f1()     //hello
	    function f1(){alert("hello")}
	</script>
  <script>
    f1()  //函数2
    function f1(){alert("函数1")}
    function f1(){alert("函数2")}  
    //js顺序执行:执行到函数1,函数1变量提升,执行到函数2,变量提升,覆盖了函数1。
  </script>

十二.面向对象

创建方式

对象——属性、方法

1.面向对象创建方式

(1) 普通方式 new Object()
 var obj=new Object()
    //添加对象属性
    obj.a=12
    obj.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=12
	obj.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=12
        obj.b="hello"
        //添加对象方法
        obj.m1=function(){alert("m1..."+this.a)}  //必须this指向否则无法调用
        obj.m1()  //调用函数
  var obj=new Object()
    //添加对象属性
    obj.a=12
    obj.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指向

  1. 对象
	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 = 23
        this.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=23
	    Person.prototype.say=function(){
	        alert("hello...")
	    }
	    Person.prototype.eat=function(){
	        alert("ganguoji")
	    }
	}
	//创建实例
	var p1=new Person()
	p1.age
	p1.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=age
        this.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=name
        this.age=age
        this.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=age
	        this.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")) //true
    alert("name" in p1) //true
    alert("name" in p2) //true

特性3——in 操作符:

只要通过对象能够访问到的属性,返回true

    console.log("name" in p1)  //true
    console.log("name" in p2)  //true
	//创建函数,判断是否为原型属性
	hasPrototypeProperty(p1,"name")

特性4

访问原型的name

	p2.name="ls"
	delete p2.name  //zs
	alert(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()  //object
    console.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()  //object
    console.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)  //zs
        console.log(des.configurable)  //true
        console.log(des.writable)  //true
        console.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)  //zs
    console.log(des.configurable)  //false
    console.log(des.writable)  //false
    console.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) // //添加值//undefined
      Person.name="ls"  //添加值
      console.log(Person.name)
      delete Person.age
      console.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 "+val
            this.age=55
        }
    }
})
    // console.log(Person._name)  //只有zs
    Person.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)  //object
    console.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=val
	    this.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)  //zs
	p1.friends.push("ww")
	var p2=new Person("ls")
	console.log(p2.name)  //ls
	console.log(p2.friends) //["a","b"]
	console.log(p1.say==p2.say)  //false
	总结:
    核心:借用父类的构造函数来增强子类的实例,完全没用到原型
    有点:1.解决了子类实例共享父类引用属性的问题
          2.创建子类时可以向父类构造函数传参
    缺点:无法实现函数的复用,每个子类实例都持有一个新的function函数,消耗内存
5、组合继承(构造函数+原型链)

—常用

   function Animal(val){
        this.name=val
        this.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=obj
	    return new F()
	}
	function Animal(){
	    this.name="animal"
	    this.friends=["ls","ww"]
	}
	var Person=new Animal()
	var p1=Beget(Person)
	console.log(p1.name)  //animal
	p1.name="zs"
	p1.friends.push("zl")
	var p2=Beget(Person)
	console.log(p2.name)  //animal
	console.log(p2.friends) //["ls","ww","zl"]
	核心:用生孩子函数得到一个“纯洁”的(没有实例属性)的新对象
7.寄生式继承
	function Beget(obj){  //生孩子函数
	    function F(){}
	    F.prototype=obj
	    return new F()
	}
	function Animal(){
	    this.name="animal"
	    this.friends=["ls","ww"]
	}
	function getSubject(obj){
	    var clone=Beget(obj)
	    clone.age=23
	    return clone
	}
	var Person=getSubject(new Animal())
	console.log(Person.name)  //animal
	console.log(Person.age)
8.寄生组合式继承—最佳
   function Beget(obj){  //生孩子函数
            function F(){}
                F.prototype=obj
                return 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=Person
        Person.prototype=p

        var p1=new Person()
        console.log(p1.name)    //Animal
        console.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=0
    function 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=1
            n=0
            var 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=23
	    location.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)      //Netscape
	    console.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  chorme
            js引擎  safari--Nitro
                    chorme--v8
            html引擎 KHTML
(2)blink    webkit的一个分支,早期的safari chrome

(3)Trident  IE内核
(4)Gecko    firefox ff内核
            js引擎   JagerMonkey
            html引擎 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])  //声明body
        console.log(document.childNodes[1].childNodes[2].childNodes[1])  //查div
        }
 //页面按照顺序加载,先加载了script,然后再加载带有id的标签,导致了script无法找到正确的id。window.onload可以让页面加载完毕后再执行里面的代码块。

1、childNodes

childNodes:每个节点都有集合属性,数组对象
—————— 表示该节点的所有节点的集合
注意:***会将元素之间的空格当作文本节点 ***

	document.childNodes[0]  
	element.firstchild
	element.lastchild
	element.parentNode    
	element.nextSibling   //相邻节点下一个
	element.previousSibling   //相邻节点上一个
	 //通过ccc的标签查找ddd aaa,title
	    window.onload=function(){
	        var a=document.childNodes[1].childNodes[2].childNodes[3].childNodes[1]
	        console.log(a)
	        var b=a.nextSibling.nextSibling
	        console.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.firstElementchild
		element.lasttElementchild
		element.parenttElementNode
		element.nexttElementSibling
		element.previoustElementSibling
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值