首页 > js 中类和实例的疑问

js 中类和实例的疑问

function Base(){
    this.say = function(){
        console.log(this);
         console.log('I am Base');
    }
}
Base.say = function(){
    console.log(this);
    console.log("i am lei!!");
}

var b  = new Base();
b.say();
Base.say();

1 类有方法,实例也有方法,类中的方法有什么作用?
2 Base类中的this指向哪里?
3 如果实例b通过new获得了堆中的存储空间,那么类有存储空间吗?

1 类有方法,实例也有方法,类中的方法有什么作用?

不管是类还是实例,都是对象,对象有方法不很正常吗?不过类上的这个方法跟实例一点关系都没有。

2 Base类中的this指向哪里?

this指向哪里在函数被调用的时候才能确定,函数定义的时候确定不了,
new实例的话this指向new出来的这个实例,
如果函数作为对象的一个属性并且作为属性被调用时,this指向该对象。

3 如果实例b通过new获得了堆中的存储空间,那么类有存储空间吗?

类也是对象,类在申明的时候就有存储空间了。

new操作符调用构造函数创建对象的步骤?
(1)创建一个新对象;
(2)将构造函数的作用域赋给新对象(因此this就指向了这个新对象)
(3)执行构造函数中的代码(为这个新对象添加属性)
(4)返回新对象


函数是对象,对象是通过函数创建。学习js面向对象这块知识的时候,需要对比其他比较规矩的面向对象语言,Base就是被我们理解为了类,这里面的say函数是说public方法,这个方法以后new出来的对象会拥有,Base函数中的this是指一个函数执行时生成的一个空对象,Base.say就是可以类比为static方法,这个也是Base的属性,所以这个函数内的this指的是Base对象,Base不就是函数吗?你这种方式定义函数的话,在预编译时就已经开辟了内存,new的过程是给实例对象开辟内存的过程


首先,js中没有类的概念,都是对象。创建一个对象方式很多,比如对象字面量,构造函数。你用的就是构造函数的方式。这个构造函数在没有new这个关键词的时候,他还是函数。这个this,在被new后,指向这个构造函数。如果没有被new,那他应该是被挂载在全局对象window下面。


var b  = new Base();

通过构造函数Bash()创建了一个对象b,这个对象里面有一个say()方法:

b.say = function(){
    console.log(this);
    console.log('I am Base');
}

say()作为b的方法,所以其内部的this指向b

Base.say = function(){
    console.log(this);
    console.log("i am lei!!");
}
Base.say();

Base作为构造函数的同时,也是Object对象,这里为Base对象定义了一个方法say()say()作为Base的方法,其内部的this指向Base

将函数名与函数功能分割开来看


首先,JavaScript 是从学 Java 来的,有一些面向对象的思想,但并不具备完整的面向对象的特性,可以说 JavaScript 里有对象,但是没有类。ES6 虽然添加了 classextends 等面向对象的特性,但其实质是个语法糖,简化面向对象模拟类和继承的代码量。

回到你的问题上来,先来看看这段代码一共有几个对象

  1. Base,即 function Base() {},这是一个函数对象

  2. Base.say() 这是另一个函数对象,它是对象 Base 的属性

  3. b = new Base(),这里产生了一个新的对象,由变量 b 引用。

  4. b.say 是在 new Base() 的时候产生的一个函数对象。

现在注意:Base 不是一个类,它只是一个函数对象。new Base() 只是 JavaScript 为了创建对象而创造一个语法,这里是把 Base 当作一个构造函数来看待,主要用于产生新对象及其 this 指针,并对这个新对象的属性进行初始化。所以在 new Base() 的时候,产生的不仅是 b 引用的那个对象,还有 Base() 中初始化产生的 this.say 这个函数对象。

这时候你也许会发现一个问题……意思是,假如

var b = new Base();
var c = new Base();

那么 b.sayc.say 是不是同一个东西呢?试试就知道了

var b = new Base();
var c = new Base();
console.log(b.say === c.say);    // false

是的,每次运行 new Base() 的时候都会产生一个新对象,以及一个新的函数对象赋值给 this。如果觉得仍然不好理解,我们来改造一下 Base

function Base() {
    var _this = {};
    _this.say = function() {
        console.log(this);
        console.log("I am new Base");
    }
    return _this;
}

var b = Base();
var c = Base();
console.log(b.say === c.say);     // false

Base 作为普通函数调用,这样也许更容易理解一些。当然,如果像这样 var a = new Base()new 来产生对象也是可以的,效果一样。

新的 Base 和旧的 Base 所产生的对象也并不完全一样,因为还涉及到原型和构建函数关联的一些特性。三言两语也说不清楚。上面的例子主要就是说明:

  1. JavaScript 中没有类,Base 不是类,只是一个构建函数对象,所以它可以有自己的方法,用起来和表态方法类似。

  2. Base.say 中的 this 其实就是指的 Base 这个对象(函数对象)。

  3. b.say 中的 this 指的是 b

  4. b.say != c.say,所以每个 say 都会战用储存空间。如果想把这个空间节约出来,需要用到原型相关特性,具体内容可以查阅资料或者专题再讨论,这里可以稍稍举个例子

function Base() {}
Base.prototype.say = function() {
    console.log(this);
    console.log("I am Base with prototype");
}
var b = new Base();
var c = new Base();
console.log(b.say === c.say);   // true
【热门文章】
【热门文章】