JavaScript学习笔记 面向对象——对象

简介

    • 对象
      • 什么是对象?
        • 语法
        • 对象内容
        • 创建对象

对象

什么是对象?

万物皆对象,但“在JavaScript中万物皆对象”说法是显然错误的。
原因:JavaScript共有六种主要类型

  • string
  • number
  • boolean
  • null
  • undefined
  • object

其中的简单类型(string、boolean、number、null和undefined)本身并不是对象。
注意:
null有的时候会被当做一种对象类型,其实是语言自身的bug
null类型
但其实null本身是基本类型。
对象的理解:

  • 对象是单个事物的抽象;
  • 对象是一个容器,封装了属性(Property)和方法(Method);
    属性:对象的状态;
    方法:对象的行为(完成某种任务)

对象是一个抽象的概念,可将其理解为:数据集或功能集,无序属性的集合,其属性可包含基本值、对象或者函数,严格讲,对象是一组没有特定顺序的值,对象的每个属性或方法都有一个名字,而每个名字都映射到一个值
每个对象都是基于一个引用类型创建的,这类型可以是系统内置的原生类型,也可以是自己自定义类型。

语法

对象可以通过两种形式定义:声明(文字)形式构造形式

  • 文字形式
var myObj = {
     
	key: value
	// ...
};
  • 构造形式
var myObj = new Object();
myObj.key = value;

构造形式和文字形式生成的对象是一样的。

对象内容

对象的内容是由一些存储在特定命名位置的(任意类型的)值组成的,即属性。对象的内容看起来是被存储在对象内部,但也只是表现形式,这些值的存储方式多种多样的,一般并不会存在对象容器内部,存储在对象容器内部的是这些属性的名称,作用就像是指针(引用)一样,指向这些值真正的存储位置
访问对象值的方法:

var myObject = {
     
	a: 2
};
myObject.a;   // 2
myObject['a'];   // 2

需要访问特定位置上的值,需要使用:

  • 点操作符
  • [ ] 操作符

如上例中.a语法被称为“属性访问”,而[“a”]语法通常称为“键访问”
两种语法的主要区别

  • 点操作符要求属性名满足标识符的命名规范;
  • [ ]操作符语法可接受任意UTF-8/Unicode字符串作为属性名

当使用string(字面量)以外的其他值作为属性名,那它首先会被转换为一个字符串,即使是数字也不例外

var myObject = {
     };
myObject[true] = "foo";
myObject[3] = "bar";
myObject[myObject] = "baz";

myObject["true"];     // "foo"
myObject["3"];        // "bar"
myObject["[object Object]"];      // "baz"

创建对象

  • 简单方式
    可直接通过new Object( )创建,调用系统的构造函数:
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( )函数,但有以下的不同之处:

  • 没有显示的创建对象;
  • 直接将属性和方法赋给了this对象;
  • 没有return语句;
  • 函数名使用的是大写的Person,而要创建Person实例,则必须使用new操作符

这种方式调用构造函数会经历以下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属性,该属性指向创建该实例的构造函数:
JavaScript学习笔记 面向对象——对象_第1张图片
对象的constructor属性最初是用来标识对象类型的,但是,如果要检测对象的类型,还是使用instanceof操作符更符合一些:

console.log(p3 instanceof Person)    // true

综上:
构造函数是根据具体的事物抽象出来的模板;
实例对象是根据抽象的构造模板得到的具体实例对象;
每个实例对象都具有一个constructor,指向创建该实例的构造函数
也可通过constructor来判断实例对象和构造函数之间的关系,但推荐使用instanceof

你可能感兴趣的:(JavaScript,javascript)