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 虽然添加了 class
、extends
等面向对象的特性,但其实质是个语法糖,简化面向对象模拟类和继承的代码量。
回到你的问题上来,先来看看这段代码一共有几个对象
Base
,即function Base() {}
,这是一个函数对象Base.say()
这是另一个函数对象,它是对象Base
的属性b = new Base()
,这里产生了一个新的对象,由变量b
引用。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.say
和 c.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
所产生的对象也并不完全一样,因为还涉及到原型和构建函数关联的一些特性。三言两语也说不清楚。上面的例子主要就是说明:
JavaScript 中没有类,Base 不是类,只是一个构建函数对象,所以它可以有自己的方法,用起来和表态方法类似。
Base.say
中的this
其实就是指的Base
这个对象(函数对象)。b.say
中的this
指的是b
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