在js中对象是由一系列的属性和属性的值组成的。属性的名字是字符串,而值是js的任意对象,在js中一切皆是对象,包括函数。
对象的声明 var a = newObject();var a = {}; 都是声明一个新对象。
而当需要定义一个具体对象的时候,可以是先声明一个空对象,然后再往里面填充属性,如
var person= {};
person.name="jack";
person.speak= function(){
console.log(this.name)
}
当然也可以是直接声明
var person= {
name:"jack",
speak:function(){
console.log(this.name)
}
};
person.speak();
这两个的效果是等价的,而在调用其属性的时候,可以用点来调用,也可以使用[]来调用,之前说过,属性名都是字符串,那么就可以person[“name”]来访问其属性。Js对属性命名没有非常严格的要求,可以在属性名中包含有点,如name.first那在这种情况之下,用点来访问其属性将会出错,使用[]来访问就不会有问题。
通过 “构造函数”来创建
function Person(name){
this.name= name;
this.speak= function(){
console.log(this.name);
}
}
var a = new Person("jack");
a.speak();
以一个函数来构造一个对象,它类似于c/c++中的构造函数,不同的是需要在这个函数中构造好其属性和方法,当然也可以在对象生成之后再动态添加其属性和方法。使用函数来构造的时候一定要用new 符号,否则就是声明一个改函数的引用。
This 不是 this
Js中的this 与c/c++中的this有着非常大的差别,在c/c++中,因为属性与方法都是直接定义在类中,此时this始终指向的是这个类的实例。而在js中,对象的方法是可以外部定义的。那么this 就不一定指向对象自身了。
一个常见的误解就是this指向自己。
function speak(){
var myName='jack';
console.log(this.myName);
}
speak();
>>undefined
在函数speak 中定义了myname这个属性,但是在输出的时候却没有和预期一样的输出,这是为何。其原因是在执行speak时,this并不指向speak这个函数,可以说this始终不会指向一个函数。This 与函数调用时候的上下文有关。上下文是什么?在刚开始学习js的时候,上下文似乎是一个非常玄乎的东西,书中也没有明确的定义其含义。为了了解其含义,再来看一个例子
function speak(){
console.log(this.myName);
}
var person={
myName:'jack',
speak:speak
}
var talk = person.speak;
talk();
person.speak();
>>undefined
>>jack
两个相同的函数却输出了不同的结果,这在我刚开始接触js的时候也非常的诧异。而其本质原因就联系着所谓的上下文。在第一个talk 中,其本质只是对函数speak 的一个引用。调用talk()和调用speak()本质是一样的。因为当前上下文并不是person对象,所以this指向的不是person对象,故不会有正确的输出。而当函数以对象名.函数名的形式来访问的时候,当前上下文就会变成该对象,此时this指向该对象。所以person.speak()可以正确输出。
让我们在来看一个例子:
function talk(){
console.log(this.myName);
}
function speak(){
console.log(this);
talk();
}
var person={
myName:'jack',
speak:speak
}
person.speak();
>>{ myName: 'jack', speak: [Function:speak] }
>>undefined
在这段代码中,我们以person.speak()形式来调用speak方法,将speak 函数的上下文设为person。企图在speak中通过调用talk函数来输出。不过结果却是不如人意。这是因为在speak方法中,this 确实已经指向person对象,但是在调用talk的时候,并不是以对象.方法名的形式来掉用,所以talk 函数中,this指向的不是person对象。让我们回到最初的问题来看看。
function speak(){
var myName='jack';
console.log(this.myName);
}
speak()函数因为上下文并不是函数自己,故在此this 不是指向函数本身。在此this应该是指向一个全局对象。因为在函数定义的时候,其本质就是在全局对象中定义一个方法。它可能是类似于 global.fun,故在直接调用时,this总会出错。
Call 和apply
我们已经知道了this和上下文有关,而和函数调用位置声明无关。那么不可能每次调用都是以对象.方法名的方式来调用。Js为我们提供了两个方法来改变函数的上下文,从而达到修改函数内部的this。
function speak(){
console.log(this.myName);
}
var person={
myName:'jack'
}
speak.apply(person);
>>jack
可以看到已经成功修改函数的上下文文为person,此时this为person ,函数可以正确的输出。
Call 和apply的第一个参数都为要设置的上下文。而apply的第二个参数为要调用的函数的参数,它是参数组成的数组,而call 在跟若干个参数的时候,参数之间用逗号隔开就可以。
function speak(text){
console.log(this.myName+text);
}
var person={
myName:'jack'
}
speak.call(person," hello");
speak.apply(person,[" hello"]);
>>jack hello
>>jack hello