前端攻城狮---js对象的高级使用(1)

本章节主要从讲解三个知识点,1.对象的理解 2.上下文this 3.面向对象的思想以及应用

对象的理解

js中对象有两种理解方式

        1.狭义的理解就是{ }定义的对象,它是一组无序的属性集合

            var demo = {

            "name":"xiaoming",

            "age":15,

            "hobby":["sleep","swim","sing"],        

            }-------->demo就是一个用{ }定义的对象    

        2.广义的理解就是js中万物皆对象,如dom,数组,function()等

            var div = docment.getElementsByTagName("div")[0];

            div.age = 15;

            div.hobby = ["sleep","sing"];

            就像之前在讲解闭包的时候,解决闭包的方法有两个方案 1.IIFE 2.强制添加属性,为什么能强制添加属性?因为它是一个对象,就是上面的div是一个dom对象,我们也可以去对其强制添加属性。

            window Date String Number等  如var str = new String("hello"); 也是一个对象

注意:基本类型不是对象

对象与json的区别

json一定是对象,但对象不一定是json

如下    json中 key一定是字符串,

    var obj = {
        "-":"-",
        "@@@":"@@@",
        "2017":"2017",
        "呵呵":"呵呵"

    }

获取数据时,一定要用[]的方法,获取的值一定要加"" 如 obj["2017"]

若是对象则有两种取值方法 xxx.key/xxx["key"]

函数的上下文

不知道大家是否还记得之前在写运动动画框架的时候,在回调方法里我们通过apply/call给方法指向一个this。为什么要指向那个this?接下来我们来一一讲解  先看看下面的demo 的输出




  
  Document
  

  
    
从输出的日志中,我们可以看到this的指向问题

其实this的指向和函数的调用者有关,onclick的调用者是my_div,win_fun的调用者是window,在平时的开发中window会省略。

  •    函数直接圆括号调用 函数上下文就是window对象
  •    函数当作对象的方法被对象打点语法调用时,函数上下文就是该对象
  •    函数是事件处理函数 函数上下文就是触发这个事件的对象 
  •    定时器调用函数,上下文是window对象
  •    数组中存放的函数,被数组索引之后加圆括号调用 this代表这个数组  

上面五点关键点,其实我们就可以总结为一句话,谁调用了方法,那么方法里的this就指向调用的对象。

下面来个小例子

    function fun(a,b,c,d,e) {//part1
       alert(this.callee.length);
    }

    function f(a,b) {
       arguments[0](10,20,30,40,50); //part2 
    }
    f(fun,5,6,7);//part3

首先我们来看看part3 第一个参数传的是一个函数,但是还没有去调用,在part2部分,通过argument这个类数组去获取实参的参数,并且去调用part3传进来的第一个参数的这个函数,到了part1部分,该函数在part2中被调用,这个时候里面的this是谁?这个this是part2的arguments,因为fun方法是在part2那里被调用了,使用方法里面的this指向的是调用对象也就是arguments,所以alert弹出的值是2。arguments.callee表示形参的类数组,所以arguments.callee.length表示的是形参的数量。

乘胜追击,再来一个例子

       var num = 4;//(1)
       var obj = {
       	  num: 6,//(2)
       	  fn:(function() {
              this.num *= 2;//(3)            var num ; this.num *=2;
              num = num *2; //(4)            num = num*2;            
              var num = 4;//(5)------------->num = 4;
              return function() {            return function(){
              	   this.num *= 2;//(6)            this.num *= 2; 
              	   num*=3;//(7)                    num *=3;
              	   alert(num);//(8)                alert(num);
              }                            
       	  })()
       }; 
       var fn = obj.fn;//part1
       alert(num);//part2
       fn(); //part3
       obj.fn(); //part4
       alert(window.num);//part5
       alert(obj.num); //part6
part1

首先我们看到obj对象的fn方法其实是IIFE,创建及调用,所以里面的this都是window,所以(3)处的num=window的num*2=8,那么(4)出的num是那个?别急我们先来看看(5)处的num,由于参数提升fn方法里的代码就变成了右边,所以(4)处的num = underfined*2 = underfined;(5)处num就变成了4;

part2

此时alert(num)输出的是window.num,由于obj的fu方法IIFE的缘故,已将window.num变成了8,所以输出8.

part3

在未执行part3之前 window.num = 8 ; obj.num = 6;  obj.fn方法里面局部变量num = 4;

因为fn是IIFE的函数,所以在此调用时,只会走(6 7 8),(6)这里的this还是window-->fn()=window.fn(),所以num是window的,num = 2*8 = 16;(7)由于闭包,这里的num是obj.fn方法里的局部变量 num = 4*3=12;(8)所以弹出12

part4

在未执行part4之前 window.num = 16 ; obj.num = 6 ; obj.fn方法里的局部变量 num = 12;

obj.fn() 只会走(6 7 8) 此时的this就是obj了 (6)obj.num = 6*2 = 12;(7)由于闭包num还是那个局部变量num = 3*12 = 36;(8)弹出的是36

part5

在未执行part5之前 window.num = 16 ; obj.num = 12; obj.fn方法里的局部变量 num = 36;

此时window.num = 16 ,弹出16

part6

此时的obj.num = 12 , 弹出12

对象的创建

new方式创建
	    function fn() {
	    	this.name = "张晓龙";
	    	this.age = 30;
	    	this.sex = "男";
	    }
	    var obj = new fn();
	    console.log(obj.age);

new的作用调用该方法,并且返回一个对象。

接下来我们再看看fn方法里面的this,在创建对象时调用了fn方法,并且返回了一个fn对象,那么谁去创建?谁去调用?方法里的this不是指定调用者?

此时fn里的this指向是是一个空对象-->{ },然后最终对象创建好了返回的对象就是该对象,不妨我们可以在fn方法中输出this。

所以new方式创建对象的过程中需要经历几个步骤

  1. 在真正执行函数之前,会创建一个局部变量,是一个{ }对象
  2. 让函数内部的this指向这个{ }对象
  3. 执行函数体
  4. 函数体执行完毕之后,返回{ }对象,返回上下文。

构造函数

        /* 构造函数*/
	    function Student(name,sex,age) {
            this.name = name;
            this.sex = sex;
            this.age = age;
            this.hobby = ["学习","运动","尊师爱友"];
            this.study = function() {
            	alert("好好学习 天天向上");
            }
	    }

	    var xiaoli = new Student("小丽","女",23);
	    var xiaohong = new Student("小红","女",18);
	    var xiaowei = new Student("小伟","男",24);

	    console.log(xiaoli);
	    console.log(xiaohong);
	    console.log(xiaowei);

同样,我们可以通过对象的方式去调用xiaoli xiaohong xiaowe 三个对象

我们来看看他们的输出日志

前端攻城狮---js对象的高级使用(1)_第1张图片

可以看到对象本身的内容就是函数。

构造函数的dom操作和注意事项
    function CreateImg(name,src) {
        this.name = name;
        this.dom = document.createElement("img");
        this.dom.src = src;
        document.body.appendChild(this.dom);
      }

        var img1 =  new CreateImg("jd","1.jpg");
        console.log(img1);

我们可以通过构造函数去创建dom对象,去操控dom对象。

	   function Teacher() {
	   	   this.name = "along";
	   	   this.age = 30;
	   	   //return 10; // return是一个基本类型 null、undefined、number、string、boolean 无视这个return 该return谁就return谁,但是return会阻止函数调用  

	   	   //return {a:1,b:2}; // 假如return是一个引用类型的话如 {}、[]、正则、函数、DOM元素、Math等,则会覆盖原有,以你返回的为准
	   }

	   var p1 = new Teacher();
	   console.log(p1);
上面代码有两个return  第一个返回的是基本类型,那么在new一个对象的时候,还是返回对象无视这个return,但在return只有的代码不执行。第二个返回的是一个对象,那么该返回的对象会覆盖new返回的对象,输出日志即可看到。


js高级之this,对象等相关知识点已经讲完,接下来会来讲js高级之原型链相关的知识点,如有表达错的请谅解,并请提出指出,且修改错误,望能共同进步。





你可能感兴趣的:(前端攻城狮)