JavaScript基础

javascript基础

javascript分类

  1. ES----脚本语言的核心内容,定义了脚本语言的基本语法和基本对象。现在每种浏览器都有对ECMAScript标准的实现。
  2. DOM----文档对象模型,它是HTML和XML文档的应用程序编程接口。浏览器中的DOM把整个网页规划成由节点层级构成的树状结构的文档。用DOM API可以轻松地删除、添加和替换文档树结构中的节点。简言之就是写的html结构最终看起来像一颗DOM树型结构
  3. BOM----浏览器对象模型,描述了对浏览器窗口进行访问和操作的方法和接口。简言之就是可以获取到浏览器的一些相关信息,比如浏览器窗口的大小/浏览器名称/浏览历史的前进后退等

JS书写位置

		我们一般把html写到body标签内,css写到head标签内,js写到结构最后,且用script的标签包裹起来

JS基本语法

	**常量**:在程序运行的过程中,其值不可以改变的量。
	**变量**:在程序运行的过程中,其值可以改变的量。

变量的声明

	var a
	var a,b,c
	var a=1

变量名命名规则

  1. 变量名由数字 字母 下划线 美元符号组成

  2. 不要数字开头

  3. 不能是关键字和保留字(有特殊含义的单词)

  4. 一个单词全部小写,多个单词,第二个单词首字母开始大写,驼峰命名 (iPad)

  5. 尽量不要重复定义

关键字和保留字

关键字:
break、else、new、var、 case、  finally 、 return、 void 、 catch  、for  、switch 、 while 、 continue、  function  、this 、 with 、default 、 if 、 throw 、 delete 、 in 、  try 、do 、 instranceof、  typeof
保留字:
abstract 、 enum   、int 、 short 、 boolean  、export  、interface、  static、  byte  、extends 、 long 、 super 、 char 、 final  、native  、synchronized 、 class  、float 、 package  、throws 、 const  、goto  、private 、transient 、 debugger 、 implements  、protected 、 volatile 、 double  、import  、public

js数据类型

基本数据类型
JavaScript的数据类型分为两种:
- **值类型(基本类型)**:字符串(String)、数字(Number)、布尔(Boolean)、未定义(Undefined)、空(Null)
- **引用数据类型**:对象(Object)、数组(Array)、函数(Function)。
String字符串

字符串是指由字母、数字、符号等字符所组成的串连的文本。JS中的字符串值必须使用单引号或双引号包裹
var a=“哈哈”

数字Number

数值 Number 数字类型的变量值通常用于算术运算,数字上也可以使用小数点“ . ”或负号“ - ”
整型
var a = 123;
浮点型
var b = 123.33;

布尔值 Boolean(true、false)

是计算机科学中的逻辑数据类型,它只接收两种值—— true(真)或 false(假)

Undefined

声明但并未赋值
var f;
console.log(f)

Null(存储内容的空对象)

null表示一个空值,跟undefined相似,但null往往是一个已声明并赋值的变量,只不过它的值的含义是“空值“
var d = null

1.从逻辑角度来看,null 值表示一个空对象指针,而这也正是使用 typeof 操作符检测null时会返回"object"的原因
2.Undefined和Null属于两种不同的类型
3.Undefined隐含着意外的空值,而Null隐含着意料之中的空值。因此设置一个变量、参数为空的时候,建议使用null而不是undefined

数据类型的检测

检测方法 typeof
var a="haha"
console.log(typeOf a)
其他数据类型类似

运算符

程序在运行的过程中需要进行大量的计算才能得到一定的结果。而运算符就是一种告诉编译器执行特定的数学或逻辑操作的符号。
运算符的分类
  1. 算数运算符
    +、- 、*、/、%
  2. 自增、自减
    ++、- -
  3. 赋值运算符
    =
  4. 关系运算符
    < 、>、== 、=== 、!=
  5. 逻辑运算符
    逻辑运算符用于检测变量、值之间的逻辑关系,逻辑运算符的左右两边必须是布尔值(如果不是,则进行强制类型转换),逻辑运算最终返回结果也是一个布尔值
    !取反
    && 并且
    || 或

运算符的优先级

	1.括号
	2.一元运算符 ++ 、--、!
	3.二元运算符 * / %
	4.二元运算符 + -
	5.关系运算符 > <   >=   <=
	6.==   ===   !==
	7.&&
	8.||
	9. 三元运算符

数据类型的转换

在程序运行和网络数据交换的过程中,最常使用的数据传输类型就是以字符串类型。而在获取到交互数据后需要对其进行算术或逻辑计算,又需要使用到其他的数据类型。
1. 隐式转换
	(1) 字符串+任何 都是拼接
	(2) 其他运算符  / - * % 等对数字的字符串都会隐性转换
2. 显示转换
 	parseFloat()
 	通过调用函数 parseFloat( ),将需要转换类型的值(或变量)传入函数,将得到该值(或变量)的浮点型数值形式
 	parseInt()
 	通过调用函数 parseInt( ),将需要转换类型的值(或变量)传入函数,将得到该值(或变量)的整型(无小数点)数值形式
 	Number()
 	其他类型转数字
 	String( value ) 
 	通过调用函数 String( ),将需要转换类型的值(或变量)传入函数,将得到该值(或变量)的字符串形式
 	连接运算符: +
 	当一元运算符“+”左右两边都有值,并且某一边的值是字符串类型时,“+”将不再代表加法符号和数学中的“正号”,而代表字符串连接符。
 	Boolean()
 	其他类型转布尔值
3.**短路与和短路或** 
	 1. 短路与 &&
	   &&符号的左侧是true,会直接返回右侧的值
	   &&符号的左侧是false,直接返回左侧的值
	 2.短路或 ||
		 ||的左侧是true,直接返回左侧值
		 ||的左侧是false,直接返回右侧值

流程控制语句

  1. 顺序结构语句 js默认由上至下执行
  2. 分支结构语句 js会根据条件的判断,决定是否执行某段代码
  3. 循环结构语句 js会根据条件的判断,反复的执行某段代码

逻辑分支

1.if语句

  • 书写格式:if (判断式){代码块}

  • if 语句 - 只有当指定条件为 true 时,使用该语句来执行代码

  • if (condition){

    ​ 当条件为 true 时执行的代码
    }

  • 请使用小写的if。使用大写字母(IF)会生成 JavaScript 错误!

2.if else语句

  • 书写格式:if(判断式){代码块1}else{代码块2}

  • 如果判断式为真,则执行语句A,否则将执行语句B

  • if (condition){

    ​ 当条件为 true 时执行的代码*
    }
    else{

    ​ 当条件不为 true 时执行的代码*
    }

  1. if…else if…else 语句
	<!DOCTYPE html>
<html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Title</title>
      </head>
      <body>
          <script>
              var score = parseInt(prompt('请输入你的成绩:'))

              if (score < 60 && score >= 0) {
                  alert('努力吧少年');
              } else if (60 <= score && score < 80) {
                  alert('及格');
              } else if (80 <= score && score < 90) {
                  alert('良好');
              } else if (90 <= score && score < 100) {
                  alert('优秀');
              } else if (score == 100){
                  alert('毕业了,你可以起飞了');
              }
              
              
             
          </script>
      </body>
</html>
  1. if的嵌套
if(条件1){    
	    条件1满足时执行的语句
	}eles{
	    if(条件2){
	        条件1不满足,条件2满足时执行的语句
	    }else{
	        条件1,条件2都不满足时执行的语句
	    }
	}
  1. 三目运算符
  • ​ 单目运算符:此运算符只需要一个操作数,如:! ++ –
    • 双目运算符:此运算符需要两个操作数,如:+ - && ||
    • 三目运算符:此运算符需要三个操作数,如:?:
  • ​ 一元表达式:由单目运算符和一个操作数组成式子。如: i++;
    • 两元表达式:由双目运算符和二个操作数组成式子。如: a+b;
    • 三元表达式:由三目运算符和三个操作数组成式子。如: a>b?a:b;
  1. switch…case语句
+ switch 语句用于基于不同的条件来执行不同的动作。
+ 书写格式:

  switch(n)
  {
  ​    case 1:
  ​        执行代码块 1
  ​        break;
  ​    case 2:
  ​        执行代码块 2
  ​        break;
  ​    default:
  ​        与 case 1 和 case 2 不同时执行的代码
  }

+ 首先设置表达式 *n*(通常是一个变量)。随后表达式的值会与结构中的每个 case 的值做比较。如果存在匹配,则与该 case 关联的代码块会被执行。请使用 **break **来阻止代码自动地向下一个 case 运行。(不然会有穿透效果)

循环语句

  1. while循环
+ while 循环会一直循环代码块,只要指定的条件为 true。

+ 语法结构:while (条件) {

  ​						要执行的代码块

  ​					}
  1. do while循环
+ do/while 循环是 while 循环的变体。在检查条件是否为真之前,这种循环会执行一次代码块,然后只要条件为真就会重复循环

+ 语法结构:		do {    

​              	   		要执行的代码块

​                        }while (条件);
  1. for循环–for循环支持多次遍历代码块
 for (语句 1; 语句 2; 语句 3) {
     要执行的代码块
}
**注释
语句 1 在循环(代码块)开始之前执行。
语句 2 定义运行循环(代码块)的条件。
语句 3 会在循环(代码块)每次被执行后执行

  1. break和continue关键字
break关键字

	+ break语句能够结束当前for、for/in、while、do/while或者switch语句的执行。同时break可以接受一个可选的标签名,来决定跳出的结构语句。
	+ 如果没有设置标签名,则跳出当前最内层结构。
	
	
continue关键字
	- continue语句用在循环结构内,用于跳出本次循环中剩余的代码,并在表达式的值为真的时候,继续执行下一次循环。
	- 可以接受一个可选的标签名,来决定跳出的循环语句。
  1. 死循环
  • 死循环:在循环中,没有结束条件的循环是死循环,程序中要避免的,否则会造成内存溢出

      + 第一种:while(true);
      + 第二种:for(;true;);
      + 第三种;for(;;);
    
  1. 扩展
    js中if和switch该如何选择?

     if 和 switch 都可以设计多重分支结构,一般情况下 switch 执行效率要高于 if 语句。但是也不能一概而论,应根据具体问题具体分析。
     
     相对而言,下面情况更事宜选用 switch 语句。
     
     - 枚举表达式的值。这种枚举是可以期望的、平行的逻辑关系。
     - 表达式的值具有离散性,是不具有线性的非连续的区间值。
     - 表达式的值是固定的,不会动态变化。
     - 表达式的值是有限的,不是无限的,一般应该比较少。
     - 表达式的值一般为整数、字符串等简单的值。
     
     下面情况更事宜用 if 语句。
     
     - 具有复杂的逻辑关系。
     - 表达式的值具有线性特征,去对连续的区间值进行判断。
     - 表达式的值是动态的。
     - 测试任意类型的数据。
    

JS数组

1.创建数组

  • 构造函数方式
    var arr = new Array(123,“哈哈”)
  • 字面量定义方式(常用)
    var arr = [哈哈",1]

2.访问数组

**元素**:数组的每一项称之为元素

**下标/索引**:每一个元素都对应着一个编号,从0开始编号

**访问元素**:数组名[下标]

**获取数组长度**  数组名.length

3.遍历数组

遍历(一次性访问所有的元素)数组:利用循环获取数组中每个元素的值

var arr = ['周杰伦', '蔡依林', '侯佩岑', '田馥甄','张三'];
for (var i = 0; i < arr.length; i++) {
		console.log(arr[i]);
}

4.数组的修改和访问

var arr1 = [1,2,3,4,5]
		console.log(arr1[0]) //1 查
		arr1[1]="嘿嘿"; // 改
		console.log(arr1); // 1,"嘿嘿",3,4,5

5.多维数组

//一维数组
var arr = [1,2,3,4,5];
console.log(arr[2]);
			
//二维数组   一维数组当中的元素,又是一个一维数组
var arrTwo = [[1,2],[3,4],[5,6]];
console.log(arrTwo[1][1]);//4
			
//三维数组
var arrThree = [
				[[1,2],[3,4]],
				[[5,6],[7,8]],
				[[9,10],[11,12]]
			]
console.log(arrThree[2][0][1]);

javascript函数

1. 什么是函数?

具有某个特定功能的代码块,其本质也是一种数据,属于对象

2. 为什么使用函数
  • 解决代码冗余问题,形成代码复用
  • 实现模块化的功能
3. 函数基本使用

JS中的函数:把一段需要重复使用的代码,用function语法包起来,方便重复调用,分块和简化代码。复杂一点的,也会加入封装、抽象、分类等思想。

3.1 JavaScript函数声明(定义)
3.1.1 字面量定义(多)
function 函数名(){
     //函数体 将原来代码拿过来就行
}
console.log(函数名)
函数的名字:动作+模块/模块+动作    costList    listCost
  • 方法名字与变量名一样都必须是JavaScript合法的标识符。
  • 在小括号之后是一个大括号,大括号内包含的语句就是函数体结构的主要内容。在函数体中,大括号是必不可少的,缺少大括号, JavaScript将会抛出语法错误
3.1.2 表达式定义(较少)
var 变量名(函数名) = function(){
   //函数体 将原来代码拿过来就行
}
console.log(函数名)
3.1.3 构造函数定义(几乎不用)
var fn3 = new Function("代码体")
console.log(函数名)
3.2 JavaScript函数调用(使用)
  • 调用方式:名字(); 函数可以多次调用
//函数声明
function fn(){
	console.log(1);
}
//函数的调用
fn();

思考:调用方法名字不加()会返回什么?

函数如果只定义 不使用 是不会执行里面的函数体的,可以将里面的函数内容理解为 垃圾代码

4. 函数声明的三要素
function add(a,b){
	var sum = a + b;
	return sum;
}
  • 功能: 看函数的名字或者函数体
  • 参数: 形参(形式参数),可有可无 本质相当于在函数体中var了一个变量,但是没赋值
5. 函数调用的三要素
add(1,2);
  • 功能: 函数调用的名字和定义的名字保持一直
  • 参数:实参(实际参数) 本质是在给函数声明中的形参赋值
  • 返回值: 函数调用本质是一个表达式,那么一定有值,值就是return出来的内容
6. 参数的个数

一般情况下,函数的实参和形参的数量应该相同,但是JS并没有这样的要求。可以不相同

案例1:正常传递对应参数

function f(a,b) {
  	alert('正常传递参数');
}
f(1,2);

案例2:实参少于形参

function f2(a,b,c) {
    console.log(a,b,c);//1 2 undefined(定义了但是没赋值)
    console.log(typeof c);//undefined
}
f2(1,2);

案例3:实参多余形参

function f3(a,b,c) {
    console.log(a,b,c)
}
f3(1,2,3,4,5,6,7)

判断是否有参数: 未知的不确定的都可以交给参数

**判断是否有返回值:如果在函数外面需要使用则返,不需要则可不返

7. JavaScript函数的分类

7.1 根据函数的归属
  • 官方函数 console.log() alert()
  • 自定义函数 fn()
7.2 根据是否有参数和是否有返回值
  • 无参无返
  • 无参有返
  • 有参无返
  • 有参有返
7.3 根据定义或者调用方式
  • 普通函数 xxx() xxx.yy()
  • 构造函数 new xxx()

8.JavaScript作用域

作用域:变量作用的范围,是一个虚拟的概念,函数定义之后就会确定该范围

作用:隔离变量

8.1 变量作用域(函数为界)
  • 全局变量:变量在整个页面中都是可见的,可以被自由的访问,在函数之外定义的变量是全局变量
  • 局部变量,变量仅能在声明的函数内部可见,函数外是不允许访问的,在函数内部定义的变量是局部变量
8.2 JavaScript 局部作用域

变量在函数内声明,变量为局部作用域。

局部变量:在函数内部用var定义的变量

function myFunction() {
    // 局部变量 只能在该函数体中使用
    var name = "嘿嘿";
}
// 形参也是局部变量的一种
function fn2(a,b){
	// a和b是形参,相当于var a,b
}
fn2(1,2)

a. 因为局部变量只作用于函数内,所以不同的函数可以使用相同名称的变量。

b. 局部变量在函数开始执行时创建,函数执行完后局部变量会自动销毁。

8.3 JavaScript 全局变量

变量在函数外定义(不被任何括号括起来),即为全局变量。

全局变量有全局作用域: 网页中所有脚本和函数均可使用。

// 在函数外面var或者不var的变量都属于全局变量
var name1 = "zhangsan";
var sex = "女";
// 此处可调用 name1 变量
function myFunction() {
  	console.log(name);
}
// 函数内部不使用var声明的变量也属于全局变量
function myFunction() {
    name1 = "lisi";
    // 此处可调用 name1 变量
}
myFunction();
console.log(name);
// 表达式的该变量也是全局
var fn = function(){
  
}
8.4 变量名重复的情况
//1. 全局变量名和全局变量名重复,根据就近原则
var d = "嘿嘿";
function fn4(){
    d = "拉拉";
    console.log(d); //拉拉
}   
fn4();
console.log(d); // 拉拉
//2. 全局变量名和局部变量名重复,根据就近原则
var f = "嘻嘻";
function fn5(){
    var f = "呵呵";
    console.log(f); //呵呵
}
fn5();
console.log(f) //嘻嘻,内部的f访问不了,所以还是全局的值
  • 全局和局部都有的 自己用自己的
  • 全局有,局部没的,局部可用全局的
  • 全局没有,局部有,全局不能用局部的

9.JavaScript作用域链

作用域链:JS中数据的查找规则。

作用域链和作用域不是一回事;

​ 作用域描述是变量起作用的区域和范围

​ 作用域链描述的程序在找变量的过程;

​ 程序在查找变量的时候,先从自己的作用域去查找,如果找到就直接使用这个变量的值,如果没有找到,会继续往上一级作用域去找,同样也是找到就使用没有找到继续往上找;直到找到全局作用域,如果找到就使用,找不到就报错(引用错误,这个变量没有定义);

10.JavaScript预解析

  • 概念:

    • 预解析分为变量预解析(变量提升)和函数预解析(函数提升)
  • 特点

    • 预解析会解析带var的变量和函数声明定义的函数function,解析函数优先级比解析变量要高,(函数覆盖变量)

    • 可以认为解析的时候分为两步,先去解析所有的函数声明定义的函数,再去解析所有的带var变量;

    • 解析过程当中,如果函数重名,会覆盖(后面的函数会把前面的覆盖掉)

      ​ 如果变量重名,会忽略;

10.1 JavaScript变量提升

var 声明的变量会被提升到当前作用域的最前面,值不提升

console.log(a);
var a = 10;
console.log(a);

以上代码会被解析为
var a;
console.log(a) // undefined
a = 10;
console.log(a) //10

不带var的不提升

console.log(a); // a is not defined
a = 10;
console.log(a) //10
10.2 JavaScript函数提升

具名函数的提升(将整个函数声明一起提升,不执行)

fn1(); 
function fn1(a,b,c) {
    console.log("嘿嘿");
}

以上代码会被解析为
function fn1(a,b,c) {
    console.log("嘿嘿");
}
fn1()

匿名函数的提升

fn1(); // fn1 is not defined
var fn1 = function(){
	console.log("111");
}

以上代码会被解析
var fn1;
fn1(); // 没有该函数
fn1 = function(){
	console.log("111");
}

总结:预解析先去解析函数声明定义的函数,再去解析带var的变量;

函数重名会覆盖,变量重名会忽略;(变量如果不带var,变量是不会进行预解析的;只有带var的变量才会进行预解析;表达式定义的函数也是当做变量去解析)

11. JavaScript函数参数的高级

11.1. 立即执行(调用)函数 IIFE(Imdiately Invoked Function Expression)

立即执行函数也叫做匿名函数自调用

  • 匿名函数后面加上一个括号即可立即执行!
(function (){
        console.log("运行匿名函数");
 })()
  • 倘若需要传值,直接将参数写到括号内即可:
(function (str){
    console.log("Hello   "+str);
})("World")
1.1 IIFE特点

1、匿名函数自调用是在定义的同时执行函数
2、匿名函数自调用只能执行一次
​ 如果需要一个函数可以执行多次,这个函数必须是有名函数
​ 如果函数没有名字要想执行必须是自调用,但是只能执行一次
3、匿名函数自调用,函数整体不会发生预解析,但是函数内部执行代码是要去预解析

4、匿名函数前面的代码一定要加;代表前面结束了

1.2 IIFE作用
  • 防止外部命名空间污染
  • 隐藏内部代码暴露接口
  • 对项目的初始化,只执行一次
1.3 全局污染

全局变量污染:大家都在全局中写代码,很容易造成命名冲突,导致代码冲突。ES6中代码冲突会直接报错。所以要养成好的习惯不要在全局去声明变量。

11.2 函数中的arguments
  • 参数对象是一个伪数组,可以使用数组方法去操作

  • 存在于每一个函数的内部

  • 可以根据该值可以获取到所有的实参

    function add(a,b,c) {
        console.log(add.length)//函数形参的个数
        console.log(arguments.length)//获取实参的个数
        return arguments[0] + arguments[1] + arguments[2];
    }
    console.log(add(1, 2));
    

案例1:输入一组数字,求平均值的函数

function f() {
    //先获取到所有的实参 使用arguments
    var sum = 0;
    for (var i = 0; i < arguments.length; i++) {
        sum += arguments[i];
    }
    return sum / arguments.length;
}
console.log(f(12, 34, 54, 32, 100, 98, 45, 34, 120));

案例2:书写一个函数 计算 三个值的和

function add(a,b,c) {
    return a+b+c;
}
console.log(add(1, 2));//NaN
12.3 callee属性

获取形式参数的个数

arguments.callee 打印出来的就是函数本身,它可以在函数递归调用的时候,派上用场

function fn(){
  console.log(arguments.length);
  console.log(arguments.callee);
}
fn();

13.函数的回调

  1. 函数是自己的定义的
  2. 函数没调用
  3. 但是函数执行了
// DOM操作:用js操作html
var oDiv = document.getElementById("box"); //获取dom 获取div结构
console.log(oDiv);
// 点击div,右侧函数就满足回调函数的三个条件
oDiv.onclick = function(){
  alert("你点我了"); 
  oDiv.style.fontSize="50px";
  oDiv.style.background="pink";
}

常见的回调函数

  1. 事件
  2. 定时器相关
  3. 数据请求ajax
  4. 框架中的生命周期

14.函数的递归

函数的递归调用,就是函数在内部自己调自己

函数的递归调用是一把双刃剑,如果设计的好,可以帮我们简单的处理事情,如果设计不好就是灾难

函数的递归要想设计好必须有两个条件

  • 必须有一个明显的结束条件,不能一直递归下去
  • 每一次调用都要有一个趋近结束条件的趋势
递归案例
// 1.2利用函数实现任意数的阶乘,且返回到函数外部
// 递的是参数,归的是值
function fn1(num){
  // 结束自调用
  if(num==1){
    return 1;
  }
  // 1.跳出函数 2.返回函数执行后的结果
  return  num * fn1(num-1);
  // 首次执行函数 5*fn1(4)
  // 自调用      5*4*fn1(3)
  //            5*4*3*fn1(2)
  //            5*4*3*2*fn1(1)
  //            5*4*3*2*1
  //            5*4*3*2*1*0*fn(-1)  
}
fn1(5)

内存

在硬件层面上,内存指的是随机存取存储器。用来储存应用运行所需要的各种数据,CPU 能够直接与内存交换数据,保证应用能够流畅运行。

在软件层面上,内存通常指的是操作系统从主存中划分(抽象)出来的内存空间。此时内存又可以分为两类:栈内存和堆内存。

JavaScript栈与堆(Stack & Heap)

栈(stack):栈会自动分配内存空间,会自动释放,存放基本类型和引用数据类型的变量

所有在函数/方法中定义的变量都是放在栈内存中,随着函数/方法的执行结束,这个函数/方法的内存栈也自然销毁。

优点:存取速度比堆快。
缺点:存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。

堆(heap):动态分配的内存,大小不定也不会自动释放,存放引用类型的对象,指那些可能由多个值构成的对象,保存在堆内存中。

堆内存中的对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能被另一个引用变量所引用(参数传递)。创建对象是为了反复利用。

程序的执行过程-案例

程序·代码见左上角
2.
代码见左上角


建议观看视频资源了解详细过程 

总结:
1、程序一开始执行,碰见了全局执行环境,首先会创建全局执行环境并且进行压栈,全局代码执行的时候依赖的就是全局环境当中的东西;比如 全局变量(全局变量如果存的是基本数据类型,那么这个值是直接存在栈当中的,如果这个变量存的是对象类型(函数、数组,对象),那么数据是要在堆结构当中开辟自己的空间专门存储的。然后把堆里面这块空间的地址存给栈当中的对应变量);

2、当程序执行碰到了函数调用;函数是比较特殊,因为它也可以执行;函数执行的时候也要有自己的环境去依赖。因此函数执行也是创建自己的函数环境进行压栈(函数执行环境一定是压在全局执行环境之上的),局部变量,是在函数环境当中存在的,只有函数执行,局部变量才会出现。函数执行完成以后,函数环境要弹出栈(销毁归还内存),局部变量也就不复存在了。

3、当函数调用完成以后,会继续执行全局代码,一直到所有的代码都执行完成,代表程序执行结束,程序结束的时候,我们的全局环境最后出栈。

JavaScript对象

JavaScript对象概念及使用
在 JavaScript 中,几乎“所有事物”都是对象。

**对象**:无序的名值对的集合(键值对)就叫做对象

面向对象和面向过程是两个思想

c语言属于面向过程的语言,java和js都属于面向对象的语言

**面向过程**:完成一件事情,全程都是自己干的

**面向对象**:完成一件事情,自己没干,都是让别人一步一步干,自己面对是这个别人就是某个对象

**作用**

- 如果要存储简单的数据(姓名、年龄)用 直接var a = 10;
- 如果要存储一堆同类型的数据 var arr = [1,2,3,4,5];
- 如果要执行一堆代码,且让这段代码的功能能重复使用,就使用函数
- **如果想要描述一个复杂的事物,比如一个人的姓名、年龄、身高、体重等等很多信息的话,可以使用对象**
2.1 字面量方式定义
var xiaohei = {
  name: "小黑",
  age:18,
  height:180,
  "weight": 140,
  hobby: ["吃饭","睡觉","打豆豆"];
  eat:function(){
    console.log("吃嘛嘛香");
  }
}

//内部组成:属性+属性值或者也叫键值对
//属性:本质上都是字符串,引号可加可不加,短线连接的单词得加引号
//属性值:可以是任意的值(变量、常量、数组、字符串、函数等)
//        如果属性值是个函数,通常会将其叫做 对象的方法

2.2 构造函数定义
//传参
var xiaohei = new Object(
    name: "小黑",
    age:18,
    height:180,
    "weight": 140,
    hobby: ["吃饭","睡觉","打豆豆"];
    eat:function(){
      console.log("吃嘛嘛香");
    }
);
//不传参,打点添加
var boyFriend = new Object();
console.log(boyFriend); 空对象
// 给对象加值
boyFriend.height = 180;
boyFriend.weight = 140;
boyFriend.hobby = ["吃饭","睡觉","豆豆"];
console.log(boyFriend);
2.3 工厂类定义
function boys(name,height,weight){
  var obj = new Object();
  obj.name = name;
  obj.height = height;
  obj.weight = weight;
  return obj;
}
var b1 = boys("白敬亭",180,140)
var b2 = boys("张颂文",180,150)

console.log(b1,b2)
3.1 对象的增删改查 []语法 (通用)
var xiaohei = {
    name: "小黑",
    age:18,
    height:180,
    "weight": 140,
    hobby: ["吃饭","睡觉","打豆豆"];
    eat:function(){
      console.log("吃嘛嘛香");
    }
};
//查  []
console.log(xiaohei["name"]) // 小黑 
//增
xiaohei["aa"] = "嘻嘻";
//删
delete xiaohei["age"];
//改
xiaohei["name"] = "小白"; //有则改
xiaohei["bb"] = "啦啦";//无则加

3.2 对象的增删改查 .语法 (常用)
var xiaohei = {
    name: "小黑",
    age:18,
    height:180,
    "weight": 140,
    hobby: ["吃饭","睡觉","打豆豆"];
    eat:function(){
      console.log("吃嘛嘛香");
    }
};
//查
console.log(xiaohei.name);
//增
xiaohei.aa = "啦啦";
//删
delete xiaohei.name;
//改
xiaohei.age = 19;//有则改
xiaohei.bb = "呵呵"; //无则加

// 执行对象方法
xiaohei.eat();
// .语法的特殊情况 如果属性名是短线连接的单词,不能用.语法访问
var obj = {
  "con-tes": 14;
}
// console.log(obj.con-tes) 达咩
// console.log(obj["con-tes"]) √

// []语法的特殊情况
var xiaohei = {
    name: "小黑",
    age:18,
    height:180,
    "weight": 140,
    hobby: ["吃饭","睡觉","打豆豆"];
    eat:function(){
      console.log("吃嘛嘛香");
    }
};
var aa = "type";
// 需求 将aa变量中的值 当作对象属性放进去
xiaohei[aa] = 2; // aa不带引号,是变量,会获取到里面的值
// xiaohei.aa = 2; 达咩
3.3 对象的遍历(for–in)
  • 语法:
for (variable in object) {
    要执行的代码
}
for...in 循环中的代码块会为每个属性执行一次。

4. 数组、函数、对象

数组是数组,数组也是对象
var arr = [1,2,3,4];
console.log(arr);
console.log(arr.length); // 对象的.语法
console.log(arr[0]);//对象的[]语法 

for(key in arr){ //遍历对象的方法
  console.log(key) //0 1 2 3
}
函数是函数,函数也是对象
funciton fn(){
  console.log("aa")
}
fn();//函数的调用方法
console.log(fn);//函数的表面样子
console.dir(fn);//函数的内在样子,里面的组成和对象一样
fn.a = 213; // 对象的.语法
console.dir(fn);//函数的内在样子,里面的组成和对象一样

5. window对象

window对象:是js中的顶级对象,浏览器打开的一瞬间,所有的数据都会放到window对象身上,也可叫浏览器窗口对象

全局中的变量和函数都会存储到window中

6 this关键字

this是Javascript语言的一个关键字。
它代表函数运行时,自动生成的一个内部对象,随着函数使用场合的不同, this的值会发生变化,也就是经常说的指向会发生变化

​this是一个内置的变量,this经常在函数/方法的内部去使用,**this在函数外部统统代表的是window**,this本质上是一个对象,this这个变量当中存储的是一个对象的地址,this主要代表的是这个函数的执行者或者调用者是谁。
6.1 普通函数内部 xxx() this指向window
function fn1() {
  console.log(this);
}
fn1();
6.2 对象方法中 xxx.yyy() this指向这个对象
var xiaohei = {
    name: "小黑",
    age:18,
    eat:function(){
      console.log(this);
    }
};
xiaohei.eat();

构造函数

7.1 内置构造函数
var x1 = new Object();    // 一个新的 Object 对象
var x2 = new String();    // 一个新的 String 对象
var x3 = new Number();    // 一个新的 Number 对象
var x4 = new Boolean();   // 一个新的 Boolean 对象
var x5 = new Array();     // 一个新的 Array 对象
var x6 = new RegExp();    // 一个新的 RegExp 对象
var x7 = new Function();  // 一个新的 Function 对象
var x8 = new Date();      // 一个新的 Date 对象
7.2 自定义构造函数
由Object实例化出来的对象类别是不固定的,比如可能是描述人、狗、车等

es5中是没有类的,但是可以通过构造函数模拟类的概念
// 自己定义的构造函数,首字母一般大写
function Person(name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
}
// 调用构造函数的时候,前面必须带 new
var p1 = new Person("cuihua"18"男");
var p2 = new Person("gangtie"19"女");
var p3 = new Person("huahua"20"x");
7.3 构造函数和普通函数的区别
- 调用方式 普通函数 xxx()  构造函数  new xxx()
- this指向 普通函数this指向window 构造函数this指向实例化的对象
- 普通函数return出来是啥 值就是啥,不return或者return后面没值,返回undefined,构造函数只要不是返回引用类型,其他都是实例化对象
function Person(name,age,gender){
  this.name = name;
  this.age = age;
  this.gender = gender;
  this.eat = function(){
    console.log(this.name+'吃卤煮~~');
  }
}		
var person = new Person('大哥',100,"男");

8. new的过程

function Dog(name,age,color){
		this.name = name;
		this.age = age;
		this.color = color;
		this.eat = function(){
			console.log('吃肉');
		}
}
var result = Dog('小黄',3,'yellow');
var d1 = new Dog('小黑',2,'black');
1. 在堆中开辟一个空间(为实例化对象准备的)
2. 会让该函数中所有的this都指向开辟出来的空间
3. 执行函数内部的代码,将属性和方法添加到该实例化对象身上(实例化的过程)
4. 最后将实例化的对象的空间地址返回出来

9.call apply bind (修改this指向)

9.1 概念
任何函数对象都有apply和call方法

**apply和call可以使用第一个参数传对象,让函数或者方法的执行者(this)指向这个对象;**

apply和call方法中的this代表是方法中的第一个参数对象。
9.2 语法
call和apply可以让一个对象执行另外一个对象的方法;

​      	函数或者方法.apply(对象,[函数的参数]);

​      	函数或者方法.call(对象,函数的参数1,函数的参数2);

​		函数或者方法.bind(对象,函数的参数1,函数的参数2);
9.3 作用
call和apply做了两件事:

1、调用的时候先把this指向改为你指定的第一个参数对象

2、然后再去自动执行使用的方法

call apply bind是对象身上的方法
function fn1(){
  console.log(this) //window--obj
}
//fn1()
var obj ={name:"aa"}
fn1.call(obj);
//使用场景
 function Dog(name, age) {
   this.name = name;
   this.age = age;
   this.run1 = function () {
     console.log(this);
     console.log("狗跑")
   }
 }

function Car(name, age) {
  this.name = name;
  this.age = age;
  this.run2 = function (a,b,c) {
    console.log(a,b,c);//1 2 3
    console.log("车跑")
  }
}
var d1 = new Dog("xiaohei", 12)

var d2 = new Car("凯迪拉克", 12)
d1.run1();
//如果车想要用狗身上的属性或者方法
// d1.run1.call(d2,1,2,3);
//apply(修改this,[参数]) 修改指向也会自动执行前面的函数
//d1.run1.apply(d2,[1,2,3]);
// bind(修改this,参数1,参数2)bind不会自动执行前面的函数,会返回一个新函数
var a = d1.run1.bind(d2); 
a()

10. instanceof的使用

console.log(typeof null)//object
console.log(typeof 对象)//object
console.log(typeof 数组)//object
// 以上三种数据类型没法具体细分开来
// A instance of B A是实例化对象 B是构造函数 判断a是不是b的实例
// 判断数组
var fn = function(){}
var obj = {}
var arr = [1,2]
console.log(fn instanceof Object); //false
console.log(obj instanceof Object); //true
console.log(arr instanceof Object); //false

console.log(fn instanceof Array); //true
console.log(obj instanceof Array); //true
console.log(arr instanceof Array); //true
// null是基本类型 Object引用类型
console.log(null instanceof Object); //false


11. JavaScript原型对象

11.1 什么是原型对象
  1. 显式原型对象

     原型对象就是函数对象的一个属性prototype的值( 地址),这个prototype属性值是原型对象, 也被叫做显式原型对象.ES5中适合在原型内部添加东西---修改。
     
     `console.dir(Villa);`
    
  2. 隐式原型对象

     只要是对象,对象身上都会有`__proto__`或者[[Prototype]](谷歌浏览器上解析)
     
     `var v1 = new Villa(1000,'中式',10000000);`
     
     `console.log(v1);`
    
11.2 原型对象的格式
function Villa(size, styleType, price) {
  this.size = size;
  this.styleType = styleType;
  this.price = price;
  //				this.live = function(){
  //					console.log('住的很舒服');
  //				}
}
Villa.prototype.live = function() {
  console.log('住的很舒服');
} //把方法添加在原型对象当中,让所有的实例化对象共享

var v1 = new Villa(1000, '新中式', 10000000);
v1.live();
console.log(v1.styleType);

var v2 = new Villa(2000, '简欧', 20000000);
v2.live();
console.log(v2.styleType);
11.3 原型链
描述的是对象在查找属性或者方法的过程

​      实例化对象在找属性或者方法的时候,先从自己的构造函数上去找看有没有这个属性或者方法,如果有,直接使用这个属性的值,如果没有,会继续顺着这个实例化的对象的隐式原型对象(\__proto__)找到这个对象的原型对象(和它的构造函数的显式原型对象是同一个),看看原型对象是否存在这个属性,如果有就使用原型对象当中的这个属性值,如果还没有,再去找原型对象的隐式原型对象(默认就是Object显式原型对象),找到以后去看看有没有这个属性,如果有就使用这个属性值;如果没有就返回undefined(代表已经找到顶了);
var obj = {
				name:'马大哥',
				age:33
			}

function Dog(name,age){
				this.name = name;
				this.age = age;
			}

Object.prototype.eat = function(){
				console.log('吃肉');
			}
var d1 = new Dog('旺财',3);
d1.eat(10,20);
obj.eat();

示例

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值