Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

对象,包装类2 #7

Open
Qhappyman opened this issue Mar 9, 2019 · 0 comments
Open

对象,包装类2 #7

Qhappyman opened this issue Mar 9, 2019 · 0 comments

Comments

@Qhappyman
Copy link
Owner

对象,包装类2

构造函数内部原理

上一节说过创建一个对象的第二种方法就是通过构造函数,那么js在构造函数时内部到底发生了什么

function student(name,sex,height){
    this.name = name;
    this.sex = sex;
    this.height = height;
}
var student1 = new student("guo","male",180);

构造函数内部必须使用this,而且构造对象必须必须使用new,有了new操作符时才会执行构造函数内部的步骤,分别有隐式三步。

  1. 在函数逻辑最前面隐式创建一个this空对象。

    function student(name,sex,height){
    //var this = {};
        this.name = name;
        this.sex = sex;
        this.height = height;
    }
    
  2. 执行this.+++ = +++;

    既然都在逻辑最前面创建了一个this对象,那么相应的this属性就会被添加到这个空对象里面,现在this对象里面就包含了name,sex,height三个属性及属性值 。

  3. 在函数最后隐式返回this对象

    function student(name,sex,height){
    //var this = {};
        this.name = name;
        this.sex = sex;
        this.height = height;
        //return this;
    }
    

    至此,返回值赋给了student1,对象实例里面便有了真正自己的属性和方法

    注意上面所说的三步都是*** 隐式 ***,那么必然有显式,那么这样到底谁的优先级在前,来看下面一个例子

    function teacher(name,sex){
        var that = {};
        that.name = name;
        that.sex = sex;
        return that;
    }
    var teacher1 = teacher("jia","male");
    

    这样创建对象的方法仍然可行,将构造函数显式保存,我们可以访问teacher1的属性,但是不提倡这种方法。(当在函数内部显式执行三步时,可不使用new操作符,因为new就是使隐式执行的标志)

    再来看几种情况

    function student(name,sex,height){
    //var this = {};
        this.name = name;
        this.sex = sex;
        this.height = height;
        return {};
    }
    

    将最后一步我们显式返回一个空对象,那么他会覆盖隐式,最后得到的实例就是一个空对象。但是我们如果返回一个原始值呢(五大基本数据类型)。

    function student(name,sex,height){
    //var this = {};
        this.name = name;
        this.sex = sex;
        this.height = height;
        return 123;
    }
    

    此时返回的是一个完全存在的对象,忽略了return语句,相当于系统只执行了自己隐式的三步。也就是说,只有你显式的返回值是一个对象时系统才会自动覆盖隐式返回。

    function teacher(name,sex){
        var that = {eye:big};
        that.name = name;
        that.sex = sex;
        return that;
     }
    var teacher1 = teacher("guo","male");
    

    同样的,当我们显式构造时,that对象的值也会被添加到新对象里,因为隐式构造其本质就是将属性添加到最前面的那个对象中,当然的that对象中的属性也没有理由不保存到外部。

    包装类

    假如我们创建一个变量

    var a = 3;
    

    这是一个原始值,不允许有自己的属性和方法,但是当我们给他添加属性呢。

    var a = 3;
    a.height = 5;
    

    我们可以访问到a.height,但是值为undefined,那么疑惑来了,既然原始值没有自己的属性和方法,那么为什么会可以添加属性呢?这就到了今天的主体,包装类型

    为了能够操作基本类型值,ECMAScript还提供了3个特殊的引用类型:Boolean,Number,String.这些类型与其他引用类型相似,但同时具有与各自的基本类型相对应的特殊行为.实际上,每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而让我们能够调用一些方法来操作这些数据。

    var num = new Number(123);
    

    数字不仅仅有基本数字,还有另一种数字,也就是对象数字,基本类型不允许有属性和方法,但是对象允许有,上面的代码中num的值仍然为123,此时我们可以给他添加属性和方法,但是如果拿num去运算,他又以基本数据123去运算,这就是基本包装类型的特殊之处,他给了基本类型一种获得属性方法的渠道。我们可以把他当对象使用,也可以当基本数据参与运算

    再看最上面的代码,既然基本数据没有自己的属性和方法,那么为什么可以打印出undefined,而且不报错,其实中间发生了一系列过程

    var a = 3;
    a.height = 5;
    //new Number(3).height = 5;销毁 
    //new Number(3).height;
    console.log(a.height);//undefined
    

    当访问一个原始值的属性时,系统不会给你报错,他会隐式创建一个包装类型,看起来可以访问,但是创建之后系统便立即将他销毁,当你访问此属性时,系统又会创建一个包装类,但是此时就不具有属性了,你可以访问,但是值为undefined。

    总的来说,包装类就是使基本类型可访问,但是又保留基本数据类型的特性。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant