20.JS高级(一)

上一篇:19.JS基础(五)

一、变量

1. 变量的定义

定义:值可以被修改的量叫做变量,就是存储数据的容器,本质上是内存空间

var a = 5;
var b = 10;
var a = 5,b = 10;
var a = b = 10;
var a = 10;
b = 10;
a = b;

面试题:属性的赋值优先级比变量高(连等的情况下)

var a = {n:1};
var b = a;
// a = b = 1; 
// 属性的赋值优先级比变量高(连等的情况下)
// a.x = {n:2}
// a = a.x
// a = a.x = {n:2};
a.x = a = {n:2};
console.log(a.x);  //undefineda
console.log(b.x);  //{n:2}

2. 变量的数据类型

  • 基本(值)类型

    • Number: 任意数值

    • String: 任意文本

    • Boolean: true/false

    • undefined: undefined

    • null: null

    • symbol es6

      var s1 = Symbol();//对象,直接调用
      
  • 对象(引用)类型

    • Object: 任意对象
    • Array: 一种特别的对象类型(下标/内部数据有序)
    • Function: 一种特别的对象类型(可执行)
    • 备注:准确来说Array和Function属于一种特别的Object类型。

3. 数据的存储

  • 基本数据存储 数据本身
  • 对象数据存储 地址值
  • 备注:内存当中存储的都是值,一个存的是数据本身,另一个存的是数据所在的内存(堆结构)地址;
var a
a = 'abcdefg' // a内存中保存的是基本类型数据
a = {}// a内存中保存的是地址值
var b = true
a = b  // a内存中保存的是基本类型数据
b = []
a = b // a内存中保存的是地址值

4. 判断变量的数据类型

  1. typeof

    typeof可以识别出基本类型String,、Number、Boolean、Undefined、Symbol,但是不能识别null。不能识别引用数据类型,会把null、array、object统一归为object类型,但是可以识别出function。

    所以typeof可以用来识别一些基本类型

    <script>
            var bool = true;
            var num = 1;
            var str = 'abc';
            var und= undefined;
            var nul = null;
            var s1 = Symbol();
    
            console.log(typeof bool); //boolean
            console.log(typeof num);//number
            console.log(typeof str);//string
            console.log(typeof und);//undefined
            console.log(typeof nul);//object
            console.log(typeof s1); //symbol
    </script>
    
  2. instanceof

    instanceof不能识别出基本的数据类型 String,、Number、Boolean、Undefined、Null、Symbol

    但是可以检测出引用类型,如array、object、function,同时对于是使用new声明的类型,它还可以检测出多层继承关系。

    判断某对象是否是某类

    其实也很好理解,js的继承都是采用原型链来继承的。比如Dog instanceof Animal ,其实就是看objA的原型链上是否有A的原型,而A的原型上保留A的constructor属性。

    所以instanceof一般用来检测对象类型,以及继承关系.

    格式:console.log(变量名 instanceof 类型)

    <script>
                    var bool = true;
                    var num = 1;
                    var str = 'abc';
                    var und= undefined;
                    var nul = null;
                    var s1 = Symbol();
    
                    console.log(bool instanceof Boolean);// false
                    console.log(num instanceof Number);// false
                    console.log(str instanceof String);// false
                    console.log(und instanceof Object);// false
                    console.log(nul instanceof Object);// false
                    console.log(s1 instanceof Symbol);// false
    
    				console.log([] instanceof Array);//true 数组
                    console.log(/^$/ instanceof RegExp);//true 正则
                    console.log([] instanceof Object);//true  对象
    </script>
    
  3. constructor

    由于null、undefined没有construstor方法,因此constructor不能判断undefined和null。

    <!DOCTYPE html>
    <html lang="en">
          <head>
              <meta charset="UTF-8">
              <title>Title</title>
          </head>
          <body>
              <script>
                  var bool = true;
                  var num = 1;
                  var str = 'abc';
                  var und= undefined;
                  var nul = null;
                  var s1 = Symbol();
    
                  console.log(bool.constructor === Boolean);// true
                  console.log(num.constructor === Number);// true
                  console.log(str.constructor === String);// true
                  console.log(s1.constructor === Symbol);//true
              </script>
          </body>
    </html>
    
  4. toString

    此方法可以相对较全的判断js的数据类型。

    格式: console.log(Object.prototype.toString.call(变量名));

    <!DOCTYPE html>
    <html lang="en">
          <head>
              <meta charset="UTF-8">
              <title>Title</title>
          </head>
          <body>
              <script>
                  var bool = true;
                  var num = 1;
                  var str = 'abc';
                  var und= undefined;
                  var nul = null;
                  var s1 = Symbol();
    
                  console.log(Object.prototype.toString.call(bool));//[object Boolean]
                  console.log(Object.prototype.toString.call(num));//[object Number]
                  console.log(Object.prototype.toString.call(str));//[object String]
                  console.log(Object.prototype.toString.call(und));//[object Undefined]
                  console.log(Object.prototype.toString.call(nul));//[object Null]
                  console.log(Object.prototype.toString.call(s1)); //[object Symbol]
              </script>
          </body>
    </html>
    
  5. 总结:至于在项目中使用哪个判断,还是要看使用场景,具体的选择,一般基本的类型可以选择typeof,引用类型可以使用instanceof。

5. 面试题讲解

  1. var b1 = {
        			b2:[2,'atguigu',console.log],
        			b3:function () {
          				alert('hello')
        			}
      		}
    console.log(b1,b1.b2,b1.b3) //{...} [2,...]  function(){...}
    console.log(b1 instanceof Object,typeof b1) //true object
    console.log(b1.b2 instanceof Array,typeof b1.b2) //true  object
    console.log(b1.b3 instanceof Function,typeof b1.b3) //true  function
    console.log(typeof b1.b2[2])  //function
    console.log(typeof b1.b2[2]('atguigu'))  // atguigu
    

如果方法的使用上 没有添加() 那么获取的是方法体
当我们获取方法体之后 在后面添加一个()的话 那就执行了方法

  1. undefined与null的区别?

    • undefined代表定义变量没有赋值 var a;
    • null代表赋值了, 只是值为null var a = null;
  2. 什么时候给变量赋值为null呢?

    • 对象初始化 var obj = null;
    • 删除对象 obj = null ==》 obj变为垃圾对象
  3. 严格区别变量类型与数据类型?(js中了解)

    • 在c/java语言当中 变量也是有类型的 int a = 10; char a = ‘b’ float a = 1.3;
    • 在js当中,变量类型是弱类型, 只有在数据确定存储之后,变量类型才确定 而且可以改变;(根据存储数据类型的不同而不同);
      • var a = ‘老马’;
      • a = 10;
    • 变量的类型是变量前面的var 是根据数据类型来确定的,数据类型是等号右边数据的类型
  4. 2个引用变量指向同一个对象, 通过一个引用变量修改对象内部数据, 另一个引用变量也看得见

    var arr1 = [1,2,3];
    var arr2 = arr1;
    arr1[1] = 22;
    console.log(arr2); //[1,22,3]
    
  5. 2个引用变量指向同一个对象,让一个引用变量指向另一个对象, 另一个引用变量还是指向原来的对象

    var obj1 = {};
    var obj2 = obj1;
    obj2 = {};
    obj2.name = 'zs';
    console.log(obj1);//{}
    
  6. 传基本数据值

    var a = 10;
    var b = 20;
    function add(a,b){
    	a = 20;
    	return a + b;
    }
    add(a,b); 
    console.log(a);  //10
    
  7. 传引用数据值

    var arr = [1,2,3];
    function fn(arr){
    	arr[1] = 22;
    }
    fn(arr);
    console.log(arr);  //[1,22,3]
    
  8. 关于内存释放(堆结构)的问题

    obj = null;

    垃圾回收机制:堆结构当中的对象数据,要想被回收释放,必须成为垃圾对象,也就是没有人再指向这个对象数据;

二、对象

1. 什么是对象?

代表现实中的某个事物, 是该事物在编程中的抽象(无序的键值对的集合),多个数据的集合体(封装体),用于保存多个数据的容器

var person = {
			name:'阿马'age:33,
			eat:funcition(){
				console.log('吃货')}
		}

console.log( typeof obj.eat());

2. 为什么要用对象?

便于对多个数据进行统一管理,为了去描述某个复杂的事物

符合人类看待事物的一般规律

3. 创建对象?

3.1 使用关键词 new创建对象
var obj = new Object();
obj.name = '大哥';
obj.age = 34;
obj.gender = true;
obj.eat = function(){
	console.log('吃卤煮~~');
	}
console.log(obj.name);  //大哥
console.log(obj);//34
obj.eat();   //吃卤煮~~
			
var obj2 = new Object();
obj2.name = '大嫂';
obj2.age = 60;
obj2.gender = false;
obj.eat = function(){
		console.log('吃炒肝~~');
	}
  console.log(obj2.name);//大嫂
console.log(obj2);//60
obj2.eat();//吃炒肝~~
3.2 使用工厂类来创建对象

** 工厂类的弊端 只能创建单一类型的对象**

function createPerson(name,age,gender){
				var obj = new Object();
				obj.name = name;
				obj.age = age;
				obj.gender = gender;
				obj.eat = function(){
					console.log(obj.name+'吃卤煮~~');
				}
				return obj;
			}
			
var person = createPerson('大哥',34,true);
var person = createPerson('大嫂',80,false);
3.3 使用构造方法创建对象

说明:

  • 之前实例是有限制的。它们只创建单一类型的对象。有时我们需要创建相同“类型”的许多对象的方法。

    创建一种“对象类型”的方法,是使用对象构造器函数。

  • 使用new运算符调用构造函数,可以构造一个实例对象,用法如下var objectName = new functionName (args)

  • 参数说明如下

    • objectName:返回的实例对象的名字
    • FunctionName:构造函数,与普通函数基本相同
    • args:实例对象初始化配置参数列表
    • 用大写首字母对构造器函数命名是个好习惯。
  • 在堆内存中开辟了一个空间,存储该对象

    • this指向的是当前的实例对象
    • this.属性的方式给当前对象添加属性或者方法
    • 不需要return,直接将对象返回
    • 构造函数会直接将对象给变量,而不是通过return返回的
3.3.1 创建构造器
function Person(name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
}
3.3.2 调用构造器

通过 new 关键词调用构造器函数可以创建相同类型的对象:
var 变量名字 = new 构造函数(值1,值2.。。)

var p1 = new Person("cuihua"18"男");
var p2 = new Person("gangtie"19"女");
var p3 = new Person("huahua"20"x");
3.3.3 为对象添加属性
为已有的对象添加新属性:
p1.hobby = "eat";  //a添加
p2.name = '小宇';  //替换

有则改之,无则加免

新属性被添加到 p1,不是任何其他 person 对象,只是p1 的属性,与p2,p3无关

3.3.4 为对象添加方法
为已有的对象添加新方法:
p1.hobby = function () {
    return "drink";
};

新方法被添加到 p1,不是任何其他 person 对象。只是p1 的方法,与p2,p3无关

3.3.5 内建JavaScript构造器

JavaScript 提供用于原始对象的构造器:

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 对象

Math() 对象不再此列。Math 是全局对象。new 关键词不可用于 Math。

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('大哥',1000,true);

思考:如果在构造函数中return了一个基本数据类型和一个引用类型对象,那么构造方法返回的是什么

// 首先构造函数不允许写返回值
// 如果写了  返回的是基本数据类型则忽略
// 如果返回的是对象类型 则返回对象数据
function Cat(name,age){
				this.name = name;
				this.age = age;
				return 1;
			}
			
			var c = new Cat('招财猫',1000);
			console.log(c);   //Cat {name: "招财猫", age: 1000}
function Cat(name,age){
				this.name = name;
				this.age = age;
				return [1,2,3,4];
			}
			
			var c = new Cat('招财猫',1000);
			console.log(c);    // [1,2,3,4]
3.4 字面量创建对象

这是创建对象最简单的方法。

​ 使用对象文字,您可以在一条语句中定义和创建对象。对象文字指的是花括号 {} 中的名称:值对(比如 age:18)。

var person = {name:"red romance", age:18, color:"yellow"};

也可以折行书写

var person = {
    name:"red romance",
    age:18,
    color:"yellow"
};

4. JavaScript对象属性

  • 属性指的是与 JavaScript 对象相关的值。
  • JavaScript 对象是无序属性的集合。
  • 属性通常可以被修改、添加和删除
4.1 定义JavaScript的属性
  • 对象的属性是由键值对组成的

  • 每个键值对,键和值之间用 :分隔

  • 所有的键都被称作是这个对象的属性,值叫做属性值

  • 对象的属性,本质上都是字符串,只不过大部分属性是可以省略引号不写的;少数情况会出现不符合命名规范的,就必须带引号

    eg:‘man-type’:‘渣男马’ //这个属性名必须使用引号;属性名不符合命名规范就得带引号

var obj = {
				name:'马志强',
				'age':34,
				gender:'female',
				"height":175,
				eat:function(){
					console.log('吃货~');
				},
				'character-type':'渣男'//这个属性名必须使用引号;属性名不符合命名规范就得带引号
			};
4.2 属性的增和改

通过简单的赋值,向已存在的对象添加新属性。

假设 person 对象已存在 - 那么您可以为其添加新属性:

  • 属性的添加的点语法

    点语法,写起来简单,但是某些场合无法使用.去操作

    • obj.weight = 90; 有则更改,无则添加

    • 下面两种情况必须使用[],其余的都可以使用.语法

      • obj.character-type = '嘿嘿';

        obj['chaeacter-type'] ='嘿嘿'
        

        无法操作,因为.后面的属性名不合法,只能使用[]去操作

      • var a = 'aaa'; obj.a = 'bbb';

        本意是要以变量当中的值为属性,添加一个‘bbb’的值 ‘aaa’:‘bbb’,这样写最终会把a当做对象的属性去操作,完全等价于obj[‘a’] = 'bbb’如果是要使用变量当中的值为属性,那么.语法也没办法操作;

        var a = 'aaa';
        person.a = '123';
        console.log(person);
        //改为
         person[a] = '123';
         console.log(person);
        
  • 中括号语法

    • obj['weight'] = 100; 有则更改,无则添加
    • obj['character-type'] = '嘿嘿'; 当对象的属性是不合法的名字必须使用[]
    • var a = true; obj[a] = 'bbb'; 如果我们需要以变量当中的值为属性去操作对象的话,必须使用[]
4.3 属性的删除

delete 关键词从对象中删除属性:

  • delete obj.age;

  • delete obj['character-type'];

  • delete obj[a];

  • delete 关键词 会同时删除属性的值和属性本身。

  • 删除完成后,属性在被添加回来之前是无法使用的。

  • delete 操作符被设计用于对象属性。它对变量或函数没有影响。

4.4 属性的查询

var person = {name:“red romance”, age:18, color:“yellow”};

  1. objectName.property eg: person.age
  2. objectName["property"]
    eg:person[“age”]
  3. objectName[expression] eg: x = “age”; person[x]
4.5 for…in语句遍历对象属性

语法:

for (variable in object) {
    要执行的代码
}

for…in 循环中的代码块会为每个属性执行一次。

案例:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>for in测试</title>
    </head>
    <body>
        <script>
            var person = {name:"Barry", age:18}; 
            for(var x in person) {
                console.log(x,person[x]);
            }
        </script>
    </body>
</html>
	var arr = [1,2,3];
			arr.forEach(function(item,index){
				console.log(index);
			})

5. JavaScript对象方法

5.1 创建对象方法
methodName : function() {
    // 业务逻辑代码 
}
5.2 访问对象方法
objectName.methodName()

案例练习:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>优化</title>
    </head>
    <body>
        <script>
            var person = {
                  name : "Barry",
                  age  : 18,
                  getname : function() {
                      return "诸葛钢铁";
                  }
                  };
            console.log(person.getname());
        </script>
    </body>
</html>

思考:如果调用方法的时候没有添加圆括号,会发生什么? //返回方法体

5.3 this关键字

​ this是一个内置的变量,this经常在函数内部去使用,this在函数外部统统代表的是window,this本质上是一个对象,this这个变量当中存储的是一个对象的地址,this主要代表的是这个函数的执行者或者调用者是谁。

this的使用场合

  • 普通函数内部 一般执行的时候都是window去执行的

    function fn1() {
    				console.log(this);     //  window
    			}
    fn1();
    

思考:

function fn2() {
				console.log(this);  //window
				function fn3() {
					console.log(this);   //window
				}
				fn3();
			}
fn2();
  • 方法内部 一般调用的时候执行者都是这个方法的对象

    var obj = {
    				eat:function(){
    					//称作方法
    					console.log(this);  //obj
    					console.log('吃');
    				}
    			}
    obj.eat();//eat方法执行者是obj或者是函数的调用者
    
  • 构造函数内部 this一般代表的是准备实例化出来的那个对象

说明:

函数当函数用又分为多种情况去使用:当普通函数用和当构造函数用
任何的函数都可以当普通函数用也可以当构造函数用
就看你调用函数的时候有没有加new  加了就是把函数当构造函数用,没加还是当普通函数用
函数是普通函数还是构造函数并不是定义说了算,而是调用说了算;
  function Car(name,color,price){
  				this.name = name;
  				this.color = color;
  				this.price = price;
  				this.run = function(){
  					// console.log('5个油。。。');
            console.log(this)   //window
  				}
  }
  //此时就说这个函数是当普通函数用的
  var result = Car('奔驰','black',200000);
  console.log(result);
  //此时这个函数内部的this 是window
  //函数的返回值看的就是return,没有return就是undefined;
  console.log(color);
  //普通函数调用,本质是在window对象上增加了name color price run属性和值
  //在外部,我们就可以通过这个window的属性拿到函数内部的局部变量的值;
  var c1 = new Car('红旗','black',10000000);
  console.log(c1);
  c1.run();
  //此时就说这个函数是当构造函数用的
  //此时这个函数内部的this 是准备实例化出来的对象,因为构造函数本身就是实例化对象用的;
  //返回值:如果没写return或者return后面是基本值,那么返回的就是实例化出来的对象本身,和return没关系
  // 如果return后面是对象类型的数据,那么返回的就是对象数据,和实例化出来的对象没关系
  • 事件回调函数内部:代表的就是添加事件监听的事件源

    var li_list = document.getElementsByTagName('li'); 
    for(var i = 0;i<li_list.length;i++){
    				// 循环的时候将每一个li都添加了一个点击事件
    				li_list[i].onclick = function(){
    					// innerHTML标签中的内容
    					this.innerHTML = '你绿了。。。。';
    					// this代表的是当前的点击对象
    					this.style.backgroundColor = 'green';
    				}
    }
    
  • call和apply调用的内部(后续讲解)

6. 面试题讲解

var a = {};
var obj1 = {
	m: 2
}
var obj2 = {
	n: 2
}
var obj3 = function() {};

a[obj1] = 4
a[obj2] = 5
a.name = 'kobe'
a[obj3] = 6;

console.log(a[obj1])   //6
console.log(a)

三、函数

1. 什么是函数?

具有特定功能的n条语句的封装体,只有函数是可执行的, 其它类型的数据是不可执行的,函数也是对象

2. 为什么要用函数?

  • 提高代码复用
  • 便于阅读和交流
  • 把一个项目模块化

3. 如何定义一个函数

function 方法名/函数的名字(){
     //要执行的代码
}
  • 方法名字与变量名一样都必须是JavaScript合法的标识符。
  • 在函数名之后是一个由小括号包含的参数列表,参数之间以逗号分隔。参数是可选的,没有数量限制。
  • 在小括号之后是一个大括号,大括号内包含的语句就是函数体结构的主要内容。在函数体中,大括号是必不可少的,缺少大括号, JavaScript将会抛出语法错误

4. 函数的2种角色

  • 函数: 通过()使用 ==> 就称之为函数
  • 对象: 通过.使用 ==> 称之为: 函数对象

5. 如何调用(执行)函数

  • test() 普通函数调用

  • new test() 构造函数调用

  • obj.test() 普通函数调用

  • new obj.test() 构造函数调用(极少)

    var obj = {
    			name:'马大哥',
    			age:34,
    			test:function(name,age){ 
    				this.name = name;
    				this.age = age;
    			}
    		}
    
new obj.eat();
   ```
  • test.call/apply(obj)

6. 回调函数

6.1 什么函数才是回调函数?

定义的,你没有直接调用, 但最终它执行了(在特定条件或时刻)

6.2 常见的回调函数?
  • DOM事件函数

  • 定时器函数

  • ajax回调函数(后面学)

  • 生命周期回调函数(后面学)

7. IIFE[匿名函数自调用]

7.1 IIFE的定义

全称: Immediately-Invoked Function Expression 立即调用函数表达式

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

function (){
    console.log("i am IIFE");
}

发现报错啦!!!

  • 解决方法只需要给匿名函数包裹一个括号即可:

    (function (){
        //由于没有执行该匿名函数,所以不会执行匿名函数体内的语句。
        console.log("匿名函数不会报错了");
    })
    
  • 匿名函数后面加上一个括号即可立即执行!

    (function (){
            console.log("运行匿名函数");
        })()
    
  • 在函数前添加 !~ + - 一元运算符

    !function (){
            alert("heng");
        }()  
    
  • 倘若需要传值,直接将参数写到括号内即可:

    (function (str){
        console.log("Hello   "+str);
    })("World")
    
7.2 IIFE特点
1、匿名函数自调用是在定义的同时执行函数
2、匿名函数自调用只能执行一次
		如果需要一个函数可以执行多次,这个函数必须是有名函数/具名函数
		如果函数没有名字要想执行必须是自调用,但是只能执行一次
3、匿名函数自调用,函数整体不会发生预解析,但是函数内部执行代码是要去预解析

7.3 IIFE作用
  • 防止外部命名空间污染
  • 隐藏内部代码暴露接口
  • 对项目的初始化,只执行一次
var a = 2
var b = 3
function sum(a,b) {
    return a + b
}
var a = 'haha';
sum(a,b);
var a = 'haha';
(function () {
     var a = 2
     var b = 3
     return a + b;
})()

8. 递归(了解)

练习:5的阶乘的递归

function fn(n){
				if(n == 1){
					return 1;
				}
				
				return n * fn(n-1);
			}
			
			console.log(fn(5));

下一篇:21.JS高级(二)

🌸友情推荐:全栈大佬笔记     Android领域肥宅

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值