API是啥?就是对象下面的属性,主要是函数属性吧?有没有不是函数的属性啊?有的就是length这种,一般都是属性,因为后面都加了一个f的。
所以很明显可以总结为API就是对象的属性,这些属性有什么用呢?就是拿来控制这个对象,对对象进行操作的。有很多特有函数,和同类型的有很多重复函数呀,所以都会放在公共属性。
得出以下结论:Object()里面填数字就返回数字对象,填字符就返回字符对象,什么都不填就返回空对象。同样的用New Number()也能返回一个number对象。但是直接Number()智能返回一个简单类型。
另外之前都是var a = new Number(1)这里直接就是new Number(1)一样的只不过没定义变量嘛。
NaN是数字哦
Array第一种用法:
跟var b = 1和var a = new Number(1)一样的,Array和Number一样是函数。不过有点区别的是var b = 1创造的是数字。let f = ['a','b']好像是对象。反正可以直接用let f = ['a','b']这样去申明数组。
说明a这是数字里面没有0,1,2,我是了对象也是没有0,1,2的丫
画了内存图知道,用Array的时候只是生成了一个length:3的属性。所以除了共有属性你只能用a.length
Array第二种用法:
有数组有哈希的时候就可以用a[0]和a[1]了,数组是默认0开始的,哈希是随便自己什么开始。
Array就上述两种用法。另外加不加new对Array来说是一样的。同理对function和object加不加new都一样。
所以总结一下
难怪以前说了句数组和函数都是对象,原来指的就是array和function
总结一下:比如var a = new Number(1)里面的var a 这部分叫做开辟一个变量这是在stack里面开辟内存。new Number (1)这部分是在heap里面开辟内存创造一个对象。这两部分是分开的,然后让a里面放的是new Number(1)的地址。所以创建函数,创建对象等这种说法的时候和var a 没关系。所以下面来列一下总共有哪些创建的方法。所有的都可以用new 函数名()的方式,这个函数名一律是首字母大写的。一般是不会用new的现在用于理解还说一下,真正用起来没人用的。除了特殊情况。
var a =1或者var a =Number(1)
var a = {1:1}或者var a = Object({1:1})
var a = [1,1]或者var a = Array(1,1),[]和{}是不一样的,把这个对象点开就会发现[]自带0,1,2
var f = function (){}或者function f(){}
一般都只用斜体的方法。
调试的时候可以直接打Number(),String(),Object,Array(),Function,除此之外全部可以用var 变量 = new 函数名()这种格式。
另外有几种简写,其中array没有简写function有简写:
var a =1
var a = '1'
var a = {}
具名函数funtion f(){},匿名函数function (){}只有这里f是小写。这里用关键字在申明函数,var什么的是
function的用法,所有字符依次排起来。
句法中new Function后面是参数和函数体。参数用大括号包起来,意思是参数可以不传,可以1个或者2个,或者N个
数组和函数是特殊的对象,对象的共有属性本来是指向Object.prototype,但是数组和对象指向的是自己的Function.prototy和Array.prototype。
为什么a叫数组,obj叫对象呢,因为他们的__proto__指向的是Array.prototype和Object.prototype。所以数组之所以叫数组因为他有数组的特点,换句话说他有数组的共有属性。好比你之所以称之为男人,因为你有男人的特征。
遍历
方方说你之所以叫他数组是你认为他是数组,所以用length来遍历,其实可以用key来遍历就看着像对象了。其实数组也是对象,还是用key来遍历比较好,key只是变量你用i也行。
伪数组
公共属性不是Array.prototype的就叫做伪数组。
唯一一个伪数组。对象不是数组,数组里面又没有指向Array.prototype的才叫伪数组。
forEach:作用是遍历数组
怎么遍历呢?要记住几句话:a.forEach后面必须传入一个函数。函数可以传入1,2,3个参数,如果1个参数,那就是value,两个参数就是,value和key,三个参数就是value,key,a
定义一个变量或者定义一个函数这条语句只做定义这件事。并未执行,执行的话要写一下这个变量。上述函数,写f()的意思是,执行这个函数,写f的意思是写出这个函数的代码。
所以d这个函数不管接收普通参数还是接收函数,实际的代码是差不多的。如果语句里面是a的话那到时候会返回a的代码,如果是a()的话会返回a的执行结果。所以实际中使用肯定是要写a()的。要不然我接收函数干嘛。
实际使用这个d函数的时候可以先把f函数创建好,直接d(f)。也可以直接在d里面写。d(function f(){console.log(1)})
所以传入函数的时候我要知道两点,1.d函数的传入变量f和d函数的代码中的f()要对应。2.传入的函数f我关心的是执行的内容
参数是f,内容是f()这是函数特有的。以往都是参数是f,内容也是f,那就是把参数传进来。如果你的参数是函数,那就把整个给传进来,但是如果参数是f内容是f()那参数只能传函数,要不然会报错。
所以要理解这种传入函数的模式,其实是理解:d函数的参数时f,内容是f(),实际运行是f的函数内容。
先写一个forEach的函数,然后参数是array和x,其中array对应的还是array参数说明是普通的传参,x对应的是x()说明x到时候要传函数进来。而且必须有两个参数传进来,因为x(array[i],i)这里有两个参数。然后使用forEach的时候先执行forEach自己的代码,遇到x()的地方用function (value,key){console.log(value,key)}中的console.log(value,key)替代。
这一张图中,array是传入参数里面的,后来方方又变了一次
这次array直接先赋值给a,然后a.就行了。不用forEach(a,function(x,y){console.log(x,y)})。这个a还能拿出来放外面的吗?
这个a能拿到外面过来已经不是上面那个问题了。这里是因为a是数组,forEach是数组的属性。所以a.forEach能这么用。理论上肯定不能把参数拿外面的操作为什么上面自己创造的forEach有两个传入参数,a.forEach只有一个传入参数啊?因为js把这个参数隐藏掉了。
本来a.forEach(function(){})=a.forEach.call(a,function(){})反正一旦有人用了forEach,他就会把谁给当作第一个参数传进来,但是这部分被隐藏掉了。反正js为了简单做了很多这些东西。好像是用this来做的。
a.forEach是一个函数
a.sort()
sort会改变原来的值,其他api都不会改变。
必须传入一个函数,这个函数必须传入两个参数,函数格式是:function (x,y){return x-y}或者function (x,y){return x-y}
反正也不用记x和y谁放前面都试一下就是了。反正多试一下挺省时间的。
内置排序应该是快排
join api
这里a.join(',')正好和a.toString()是一样的。a.toString是把a转化为字符正好是给他加逗号。join是可以加任何东西的。
concat api
用concat可以产生一个新的数组,复制一个数组不是赋值给b一个数组。
push api
map
通过乱写就能发现这个API的本质,难怪方方经常乱写因为一一对应容易理解错。方方有点强!
比如上面就发现了2个本质:
1.传入的参数的顺序其实是value,key,因为我把第二个参数value*2以后打出来是1,2,4,6其实对应的是0,1,2,3所以是原数组a的key不是value。
2.map这个API不做传入数组的其他变化,仅仅是遍历了一遍,然后key和value顺序换一下,然后push成另外一个数组而已。因为我return哪个参数他就能乖乖追加对应的参数*2的结果。这里写了return value*2为什么能return一个数组呢?实际代码肯定不是return value*2就结束了。实际的代码肯定是value*2以后存起来,然后追加。最终return了一个数组x。
记住这么用就行:1. 不管三七二十一把数组遍历起来, 一个参数就可以把数组联系起来了。 每次遍历都把return后面的计算一下 2.计算好的存起来,组成新数组 ,关键有个push操作3.return新数组
现在再来理解一下map的由来,本来我想把a*2但是直接这么操作失败了,为啥丫?因为哪有这么简单就乘以2了,你得用循环把每个value拿出来,然后再追加回去组成一个新的数组。以前的话把a1,a2拿出来再给b1,b2哈希的话没顺序直接push追加就好了。然后我这个函数比较复杂而且可能会用错,所以给你精简一下就是传入value和key,然后return value*2就可以了。实际上代码要复杂点。
突然想到为什么要把value放前面了,因为函数可以传入一个参数也可以传入两个参数。如果只有一个参数默认是第一个value,如果两个是value,key。当时实际上有用的只有value,所以两个参数的时候把value放后面,用一个参数的时候又默认第二个参数value显然是不合理的。
在遍历的功能上面,map和forEach一模一样。除此之外map还可以有返回值,但是forEach没有返回值
filter
filter的本质判断return后面的东西真假,如果真就追加,如果假就不追加。所以a = [1,2,3,4],如果判断value的话全是1以上的就会全部追加,如果判断key的话第一个是0所以不追加。然后这边也是key和value反的。
同样的也是判断a这个数组的value值%2===0是不是真,真就追加
记住这么用就行:1.不管三七二十一把数组遍历起来,一个参数就可以把数组联系起来了。每次遍历都看一下return后面的是不是真。当然return后面有参数的话你当然得传入参数了。 2.真的就把遍历对应的value保存下来,最终组成一个新数组。关键有个push操作 3.return新数组
filter和map一起用
reduce
reduce必须符合这个格式,sum为上一次的结果,n为当前的value,0为初始sum。然后sum+n的结果作为下一次遍历的sum
所以如果这么写的话这个sum没得n好加那永远都是初始值0,所以return sum*2肯定等于0。
通过上面这两张图可以看出reduce的本质:1.不管三七二十一把数组遍历起来,联系数组只需要一个参数。但是要相加就得再引入一个参数和这个参数的初始值。然后执行return之前的操作。然后把return后面的记下来,所以如果没有sum+n的话每次遍历都会刷新上一个n,最终只返回最后一个return。 和map、filter的区别在于没有push操作。
所以其实return这个操作可以最后看,先看其他的。比如第一张图其他代码就是遍历数组然后追加到新的数组上。最后return一下这个数组。
所以自己一直没弄出来是因为else没有写return sum吗,果然还是得搞清楚原理啊。现在懂了,n=1的时候return 0+1,然后n等于2的时候你还得ruturn上一个sum给下一个sum,要不然进行不下去了。所以else里面也要写代码就对了。上面老师这个是高级写法。判断然后:两边是if和else的执行语句。
这里用箭头的代码,map和filter也直接就用一个参数了。