万物皆对象,但“在JavaScript中万物皆对象”说法是显然错误的。
原因:JavaScript共有六种主要类型:
其中的简单类型(string、boolean、number、null和undefined)本身并不是对象。
注意:
null有的时候会被当做一种对象类型,其实是语言自身的bug
但其实null本身是基本类型。
对象的理解:
对象是一个抽象的概念,可将其理解为:数据集或功能集,无序属性的集合,其属性可包含基本值、对象或者函数,严格讲,对象是一组没有特定顺序的值,对象的每个属性或方法都有一个名字,而每个名字都映射到一个值
每个对象都是基于一个引用类型创建的,这类型可以是系统内置的原生类型,也可以是自己自定义类型。
对象可以通过两种形式定义:声明(文字)形式 和 构造形式
var myObj = {
key: value
// ...
};
var myObj = new Object();
myObj.key = value;
构造形式和文字形式生成的对象是一样的。
对象的内容是由一些存储在特定命名位置的(任意类型的)值组成的,即属性。对象的内容看起来是被存储在对象内部,但也只是表现形式,这些值的存储方式多种多样的,一般并不会存在对象容器内部,存储在对象容器内部的是这些属性的名称,作用就像是指针(引用)一样,指向这些值真正的存储位置
访问对象值的方法:
var myObject = {
a: 2
};
myObject.a; // 2
myObject['a']; // 2
需要访问特定位置上的值,需要使用:
如上例中.a语法被称为“属性访问”,而[“a”]语法通常称为“键访问”
两种语法的主要区别:
当使用string(字面量)以外的其他值作为属性名,那它首先会被转换为一个字符串,即使是数字也不例外
var myObject = {
};
myObject[true] = "foo";
myObject[3] = "bar";
myObject[myObject] = "baz";
myObject["true"]; // "foo"
myObject["3"]; // "bar"
myObject["[object Object]"]; // "baz"
var person = new Object()
person.name = 'Jack'
person.age = 18
person.SayName = function(){
console.log(this.name)
}
每次创建new Object( ) 比较麻烦
var person1 = {
name:'Jack',
age:18,
SayName:function(){
console.log(this.name)
}
}
var person2 = {
name:'Mike',
age:20,
SayName:function(){
console.log(this.name)
}
}
代码太过冗余,重复性过高
function createPerson(name, age){
return {
name: name,
age: age,
SayName:function(){
console.log(this.name)
}
}
}
var p1 = createPerson('Jack', 18);
var p2 = createPerson('Mike', 20);
console.log(p1 instanceof Object); //true
问题:并没有解决对象识别的问题,即怎样知道一个对象的类型
function Person(name, age){
this.name = name
this.age = age
this.SayName = function(){
console.log(this.name)
}
}
var P3 = new Person("Mia", 24)
console.log(P3 instanceof Object) // true
console.log(P3 instanceof Person) // true
Person( )函数取代了createPerson( )函数,但有以下的不同之处:
这种方式调用构造函数会经历以下4个步骤:
①创建一个新对象,开辟存储空间;
②将构造函数的作用域赋给新对象(因此this就指向了这个新对象),即把this设置为当前的对象;
③执行构造函数中的代码,即设置属性和方法的值;
④返回新对象,即将this对象返回;
实例说明:
function Person(name, age){
// 当使用new操作符调用Person()的时候,实际上这里会先创建一个对象
// var instance = {}
// 然后让内部的this指向instance对象
// this = instance
// 接下来所有针对this的操作实际上操作的就是instance
this.name = name;
this.age = age;
this.SayName = function(){
console.log(this.name);
}
// 在函数的结尾处会将this返回,也就是instance
// return this
}
总结:
创建对象的三种方式:
①字面量的方式;
②调用系统的构造函数;
③自定义构造函数;
构造函数和实例对象的关系
构造函数:创建对象
实例对象的构造器就是构造函数
var P3 = new Person('Mia', 27)
console.log(P3.constructor == Person) // true
console.log(P3.__proto__.constructor == Person) //true
console.log(P3.__proto__.constructor == Person.prototype.constructor) //true
使用构造函数的好处:代码简洁,同时可以识别对象的具体类型了
在每一实例对象中的__proto__中同时有一个constructor属性,该属性指向创建该实例的构造函数:
对象的constructor属性最初是用来标识对象类型的,但是,如果要检测对象的类型,还是使用instanceof操作符更符合一些:
console.log(p3 instanceof Person) // true
综上:
构造函数是根据具体的事物抽象出来的模板;
实例对象是根据抽象的构造模板得到的具体实例对象;
每个实例对象都具有一个constructor,指向创建该实例的构造函数
也可通过constructor来判断实例对象和构造函数之间的关系,但推荐使用instanceof