JavaScript学习(三)(for循环,函数及其作用域,this,原型对象及原型链,数组字符串常用方法(这个多看看!))(未完成)

for循环,if循环,初识函数,this关键字

一,关于for循环与if循环的嵌套使用

1.求出指定数组arr的平均值和大于平均数的值

思路分析:

①遍历数组使用for循环
②求和对sum进行赋值操作
③求出平均值sum/arr.length
④作比较并输出大于平均数的值if

代码实现:
var a =[5,9,6,3,7,4,2,13,19,27];
        var sum=0;
        var average;
        for (var i=0;i<a.length;i++){ //这里for循环遍历数组
            sum+=a[i]; //求和并保存总和在sum变量中
        }
        average=sum/a.length; //求出平均数
        console.log("该数组平均数为:"+average)
        for (var i=0;i<a.length;i++){ //遍历数组元素
            if (a[i]>average){ //输出大于平均值的元素
                console.log("大于平均值的数组元素:"+a[i]);
            }
        }

2.将指定数组a从大到小排列

思路分析
代码实现
		var a = [4,7,3,1,9];

        for(var i =0;i<a.length-1;i++)
        {
            for(var j=0;j<a.length-i-1;j++)
            {
                if(a[j]<a[j+1])
                {
                    var temp = a[j];

                    a[j]=a[j+1];

                    a[j+1]=temp; 
                }
            }
        }
        console.log(a); // [9,7,4,3,1]

二,初识函数与this关键字及对象

1.函数

1.定义函数的两种方式
①函数式声明(直接写)

function f(){
}

②以函数表达式的方式定义函数(即声明一个变量来储存该函数)

var a = function f( ){
}

提示:函数的声明与变量声明相同,加载初期
区别:调用第一个函数是直接写f();即可
但是第二个函数的调用就只能写a();f();就调用不到了
③自调用函数(又叫及时执行函数)或者说匿名函数

(function(){
	console.log(0)
})()

该函数涉及到的this指向是全局变量
2.数据类型
函数本身也是一种数据类型,首先函数是一种对象,所以它属于引用数据类型,其次既然是对象,那就是也可以使用语法糖的形式

例子
var Person = function(name, age, sex){
    //something
};
Person.prototype.body = function(){
    //some body
};
Person.prototype.head = function(){
    // person head
};
/*use Person Object*/
var tengfei = new Person("tengfei",22,"male");
tengfei.body();
tengfei.head();

3.函数中的实参和形参
形参相当于函数中定义的变量,实参是在运行时的函数调用时传入的参数。
可以类比为形参就是函数声明时的变量,实参是我们调用该函数时传入的具体参数。
小知识:既然上面说到函数也是一种对象,可以使用语法糖的方式去调用下面的属性,这里就可以使用fn.length去查看函数的形式参数的格式,这里的fn指的是函数的名字,如果用一个变量比如a去接收函数的话那函数的形式参数个数查看就用变量名a.length去查看
4.当传入的参数过多或者过少的情况
①过多,不影响,当想用多出来的实参时,写入arguments语句,然后arguments就会把传入的参数按顺序放入arguments这个类数组中,然后当需要使用参数时就像调用数组里的元素一样去调用arguments的元素
②过少,则形式参数的返回值是undefined

5.方法
当函数在对象中,作为对象数组的一个成员,他有一个特殊名字叫做方法,也就是说对象数组里的所有成员,除了当成员是函数时被叫做方法,其他的成员就叫做对象的属性

PS:这里提到一句,方法只能由对象访问,方法的访问者一定是方法的持有者,但是方法的调用者不一定是方法的持有者(后面再补充啦)

2.this关键字(今日份爆炸〣( ºΔº )〣)

1.this是系统提供的一个关键字,它代表一个对象,它代表的是代码执行环境对象(至今不理解╭(°A°`)╮),这么来解释就比较容易理解了,首先一定有个对象去调用函数,this代表的是代码执行环境对象,也就是说谁去调用这个函数,谁就是this代表的对象,即函数的调用对象是this代表的对象

2.例题

			 function  fn(num1,num2) {
			 	console.log(this)//win
			 	console.log(num1)//100
			 	console.log(num2)//obj1
			 }						
			 var obj1={name:"obj1"}
			 obj1.say=function(cb) {
			
			 	var obj2={name:"obj2"}
			 	obj2.say=cb
			 	cb(100,this)//cab(100,obj1)
			}									
			obj1.say(fn)

直接来个难一点的题hhh
思路分析:先按顺序来。
首先声明了一个fn函数,有两个形参,然后下面是打印this代表的对象,num1的值,以及num2的值。
然后声明了一个对象obj1,里面存放了name属性其值为obj1。
再是给obj新添加了了一个方法say
方法say里声明了对象obj2,里面存放了name属性其值为obj2。
然后将obj2新添加一个属性它的值为形参cb接收到的实参的值
然后调用函数cb并传入参数100和this
最后obj1调用它对象数组下的方法say并传入实参fn

首先我们说一下console.log(this)//win这句,这里先去看什么时候,是谁让这个代码块运行起来,也就是何时fn函数被调用了,看到这句cb(100,this)//cab(100,obj1)看似是调用cb函数,但是阅读整个结构知道cb实际存储的是传入进来的实参的值,这里是把fn函数作为参数传入进来用cb来存储,所以这一句实际上是在执行fn函数,这里要补充一点fn实际上是它上级Window的属性,所以调用fn函数的调用者是window。

这一句很简单,console.log(num1)//100就是打印100就不提了

cb(100,this)//cab(100,obj1)这句同理,什么时候谁让这个代码跑起来的,谁去调用了这个函数,所以就看到最后一行代码,obj1调用它对象数组下面的方法say,这个方法会运行,函数根据位置不同叫法也不同,这里也是函数嘛,所以要让这个函数运行起来,实际上是obj1调用它对象数组下面的方法say,所以这里的this指代的对象时是obj1,作为参数传进fn的参数num2里,所以console.log(num2)//obj1打印的是obj1

完毕!(^ワ^

3.对象

1.关键字new
new 后面跟的是一个函数名
用new来调用函数
1.找一个对象,构造函数prototype属性指向的原型对象,对这个对象进行扩展,扩展出来的对象就是新创建的扩展对象
2.用这个扩展对象去调用new后面的函数(构造函数)
3.表达式的结果:
如果函数的返回值是数据基本数据类型,表达的结果就是这个’构造过’后对象
如果函数的返回值是引用数据类型,表达式的结果就是函数的返回值,创建过的对象就消失了
关于构造函数
构造函数的第一个字母(没有规定必须大写,但是一般为了跟普通的函数区别开,要大写)(而且如果没有写过原型对象,这里针对的自构建的函数,也就是新声明的。)
每一个函数都有一个属性叫prototype==>每一个对象(引用数据)都有一个__proto__
①.如果把它当做普通函数调用,prototype这个属性就没有什么用
2.如果用new关键字来调用函数,这个prototype属性指向的对象就是创建的对象的原型对象
3.把prototype属性指向的对象 放在扩展对象的__proto__属性中(也就是说扩展对象的原型对象的属性__proto__指向的是构造函数属性prototype指向的原型对象)
4.我们称一个对象的__proto__属性指向的对象为这个对象的原型对象

Ps:关于对象的设置与获取
获取
xx.xx 取对象的成员:先取扩展空间的成员 扩展空间没有 就去__proto__属性里取,一层一层依次向上取,直到null都没有,就取到undefined
设置
obj.xx=100
不管原型上有没有这个属性,都会在自己(扩展空间去操作)

2.例子

function fn () {
        	this.name="karen"
        	this.say=function () {
        		console.log("666")
        		console.log(this)
        	}
        	return true
        }
        var re=new fn()
        //var re={} ;  re.fn()
        //console.log(re)//{name:"karen",say:func}
        var fm=re.say

        fm()//"666" window
        re.say()"666" fn 这一行暂时想不通

4.原型对象(新增)

原型对象
一个对象它为什么有点语法? 为什么有[]取数据的方法? 为什么能够保存数据 为什么能够调方法 ?
是因为系统为我们做出了这些功能? 原型对象上就有这些功能
对象的原型模型对象称为原型对象==>对象自己没有的属性和方法,原型对象上有的它也能用
(结合new关键字一起理解)
PS(1.任何对象都有一个原型对象,这个对象的constructor属性指向了这个对象的构造函数。
2.构造函数的意义:创建对象,类型划分)

4.1原型链(扩展)

1.简而言之,就是不仅仅是创建的对象有原型对象(针对new而言),原型对象也有原型对象,这样一层一层的向上找,这里下面简单的写了其中一部分,

在这里插入图片描述

4.作用域(新增)

1.没有函数就不谈作用域,作用域是针对与函数而言的
2.关于变量,window下的声明的变量叫做全局变量所有区域都可以用,函数作用域下声明的变量叫局部变量(仅限本区域有效)
所以也可以这么来说,即函数里面可以访问外面的数据,函数外面不能访问里面的数据
3.函数的调用(注意):函数的代码执行,是在函数声明的作用域下执行 不是在调用的作用域下执行代码,例

 	   var name = 'lili';
       var obj = {
            name: 'liming',
            prop: {
                name: 'ivan',
                getname: function() {
                    return this.name;
                }
            }
       }
       console.log(obj.prop.getname()); //getname()是在prop下声明的,所以打印的是ivan
       var test = obj.prop.getname;
       console.log(test()); //test()是在window下声明的,所以打印的是lili

4.关于函数的声明提前问题
①如果是显式声明,则提前到本作用域的第一行
②如果是隐式声明,则提前到全局作用域第一行
③这里也就顺带一提声明的相关问题,做题的总结:
当同一个作用域内有相同的标识符,他们的声明提前顺序如下
1.变量声明
2.形参声明
3.形参赋值(实参给形参上数据)
4.函数声明
(后来做题的时候发现这几句简直太重要,所以提醒自己在做题的时候一定要先把这几个提升,最好是自己把真正的代码写出来,就可以一气呵成)

一些方法

一,字符串
1.charAt

简而言之就是取出指定字符串对应下标的字符
例如

var str = "thnjk";  
var re = str.charAt(2);

打印结果就是n

2.concat

拼接字符串,如

 var str = "thnjk";
    var str1 = "nmd"
    var re = str.concat(str1,str,str1)

会将传入的字符串全部拼接起来,可以容纳多个参数

3.indexOf

用于检测子串是否含有指定字符串,有则返回第一次检测到该字符串的起始位置,没有则返回-1
Ps:1.lastIndexOf是从末尾开始检测,同理indexOf,只是说是从后面向前面检测

4.slice
str.slice(s,e)

返回一个新的字符串,包含从 s 到 e (不包括该元素)的 str 中的元素。
(方法并不会修改字符串,而是返回一个子字符串)

如果是数组,则返回一个新的数组,效果同上
(方法并不会修改数组,而是返回一个子数组)

5.split

把一个字符串分割成字符串数组。
将字符串以指定字符(第一个参数)进行分割,(第二个参数)返回指定数目个数的字符串

var str = "thnjk";
 var re = str.split("n")

打印结果“th”,“jk”,存放在数组中
(该方法可以将字符串转换成数组)
(Array.from同样也可以)

6.substr&substring

都是返回一个新字符串(指定长度),不同的是传入的参数
substr:第一个是起始下标,第二个是截取字符数
substring:第一个是起始下标,第二个是结尾下标(但不包括该下标)

二,数组
1.concat

连接两个或更多的数组,同字符串concat。

2.join

将数组所有元素以指定分隔符来分割数组中的元素,成为一个字符串(该方法会使数组转化为字符串)

var arr = new Array(3)
arr[0] = "George"
arr[1] = "John"
arr[2] = "Thomas"

console.log(arr.join("."))//George.John.Thomas
3.pop

删除数组最后一个元素并返回该值,然后该方法会改变数组的长度
自我实现思路:
(可用for循环能实现的,不过循环长度要比原长度减一)

4.push

向数组的末尾添加一个或更多元素,并返回新的长度。
自我实现思路:
(直接设置原长度+1下标的元素的值就行了)

5.reverse

颠倒数组中元素的顺序。
自我实现思路:
(for循环倒着循环数组)

6.shift

删除并返回数组的第一个元素
自我实现思路:
(先取出最后一个元素然后for循环,重新遍历数组,其长度-1)

7.slice

从某个已有的数组返回选定的元素并成为一个新数组,且该数组并不是修改原数组,而是返回一个子数组
自我实现思路:
(for循环,将起始下标和结束下标设为形参,传入for循环的起始下标和结束下标)

8.sort

对数组的元素进行排序
自我实现思路:
(冒泡排序即可)

9.splice

删除元素,并向数组添加新元素。

var re=arr.splice(1,2,"hello","h5")//从下标为1的位置删除2个元素,然后就在这个位置添加"hello","h5"元素

这里的三个参数:
第一个是规定添加/删除项目的位置,负数则是从倒数开始
第二个是删除项目数量,为0,就不会删除项目
第三个是增加的项目

10.unshift

向数组的开头添加一个或更多元素,并返回新的长度。
自我实现思路:
(将添加的元素放入类数组,转为数组,再用concat将原数组和新数组拼接)

遍历器(常用归纳)
字符串数组方法常用,思路归纳
谈谈你对函数的理解
(待解决问题)

一些总结

方法的自我实现有利于思维的拓展
原型与原型链的思维,会构成一个完整的体系,让编写者清楚地知道自己的行为(尤其是对象相关问题)
this,回调函数,闭包,作用域是核心,思维的理顺利于业务的开发和工具设计

关于学习,恒心比起一鼓作气更为重要,当学完原型链之后,整体出现斗志下滑的情况,学习状态松懈,需要及时调整心理,比如突然考试袭击,降低自己浮躁的心态,方法虽然简单,又多,但是却是极其实用的工具,记住利于业务,自我实现方法利于思维与深层次的学习,和构成系统的完整性

(关于方法的学习,最好是先有完整的思路体系,再去对对应的思维树去回忆对应的方法,构建知识体系远比方法的记忆和掌握更重要)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值