function printPerson(name, age, sex....) {
}
// 函数的参数如果特别多的话,可以使用对象简化
function printPerson(person) {
console.log(person.name);
……
}
所谓对象就是真实世界中的实体,对象与实体是一一对应的,也就是说现实世界中每一个实体都是一个对象,它是一种具体的存在,可以发现身边很多对象,汽车,狗,人等,这些对象都有一个属性和行为。
比如一只狗,那么它的属性有名称、品种、颜色、体重;行为有吠叫、摇摆、跑等。
JavaScript语言没有“类”,而改用构造函数(constructor)作为对象的模板。前面说过,“对象”是单个实物的抽象。所以,通常需要一个模板,表示某一类实物的共同特征,然后“对象”根据这个模板生成。所谓“构造函数”,就是专门用来生成“对象”的函数。它提供模板,作为对象的基本结构。比如var date1=new Date()是通过调用Date的构造函数Date()(这里可以理解为一个类)来创建一个日期对象。一个构造函数,可以生成多个对象,这些对象都有相同的属性和行为,但是属性值可以不同。
在 JavaScript 中,不会创建类,也不会通过类来创建对象(就像在其他面向对象的语言中那样),JavaScript 基于 prototype(原型),而不是基于类的。
在Javascript没有类和接口,只有对象,而根据ECMAscript的定义,对象是“无序属性的集合,其属性包含基本值,对象或者函数”。
需要注意的是,在ECMAscrip6.0中,已经使用class来定义类了。
对象object是JavaScript的核心概念,也是最重要的数据类型。JavaScript的所有数据都可以被视为对象。对象是一个容器,封装了属性(propert)和方法(method)。所谓属性,就是对象的静态状态;所谓方法,就是对象的动态行为。
JavaScript的对象是无序属性的集合。
其属性可以包含基本值、对象或函数。对象就是一组没有顺序的值。我们可以把JavaScript中的对象想象成键值对,其中值可以是数据和函数。
对象的行为和特征
特征---属性:事物的特征在对象中用属性来表示。
行为---方法:事物的行为在对象中用方法来表示。
在JavaScript中,其中一种定义对象的方法如下:
var o = {
p: "Hello World",
sayHello:function(){
return p;
}
};
上面代码中,定义了一个对象o,这个对象内部包含2个键值对:p和sayHello,其中p键值对是描述静态属性的;sayHello键值对是描述对象的动态行为的。属性名与属性值之间用冒号分隔。
p是对象的属性名,字符串“Hello World”是对象的属性值。sayHello是对象的另一个属性名,属性值是function(){return p; }。
如果对象内部包含多个属性对,每个属性对之间用逗号分隔。 需要注意的是,上面的代码后台隐式调用了new Object()这个构造函数创建了一个对象o,再通过键值对定义静态属性动态行为。
对象又分内置对象和自定义对象,其中内置对象是指JavaScript中已经定义好的,比如我们之后学的Date、Array、Math、String等,这些内置对象提供了许多方法和属性,只管调用和使用即可,比如Math对象中的PI和E是属性,pow(x,y)、sin(x)、sqrt(x)等方法。
而在这一小节里,主要介绍自定义对象的使用。
对象字面量
var hero = {
name: '黄忠',
weapon: '弓箭',
equipment: ['头盔', '靴子', '盔甲'],
blood: 100,
attack: function () {
console.log(this.name + ':射箭');
},
run: function () {
console.log(this.name + ': 加速跑');
}
}
console.log(hero.name);
console.log(hero.equipment);
hero.attack();
hero.run();
new Object()创建对象
// Object 是一个构造函数
// new 的方式来调用构造函数
// new Object() 调用构造函数 会在内存中创建一个对象
var hero = new Object(); // 创建了一个空的对象
// 打印一个不存在的属性 输出 undefined
// console.log(hero.name);
// 属性
// JavaScript的动态特性
hero.name = '关羽';
hero.weapon = '青龙偃月刀';
hero.equipment = ['头盔', '靴子', '赤兔马'];
hero.blood = 100;
// 方法
hero.attack = function () {
console.log(this.name + ': 射箭');
}
hero.run = function () {
console.log(this.name + ': 加速跑')
}
工厂函数创建对象
function createHero(name, weapon, equipment, blood) {
var hero = new Object(); //返回一个空的对象
// 属性
hero.name = name;
hero.weapon = weapon;
hero.equipment = equipment;
hero.blood = blood;
// 方法
hero.attack = function () {
console.log(this.name + ':攻击');
}
hero.run = function () {
console.log(this.name + ':加速跑');
}
return hero;
}
var hero1 = createHero('黄忠', '弓箭', ['头盔', '靴子'], 100);
var hero2 = createHero('刘备', '剑', ['头盔', '盔甲'], 100);
自定义构造函数
function Hero(name, weapon, equipment, blood) {
// this 动态的给对象增加成员
// this 指向了当前对象
this.name = name;
this.weapon = weapon;
this.equipment = equipment;
this.blood = blood;
this.attack = function () {
console.log(this.name + ':攻击');
}
this.run = function () {
console.log(this.name + ': 加速跑');
}
}
var hero1 = new Hero('黄忠', '弓箭', ['头盔', '靴子'], 100);
var hero2 = new Hero('刘备', '剑', ['头盔', '盔甲'], 100);
this代表的是当前对象。
但是构造函数方有个缺点,就是对象的方法放在了构造函数内部,这样每创建一个方法就会需要多占用一些内存,所以js给构造函数设计了一个prototype属性,用来存放对象的方法:
function Student(name,age,id){
this.name=name;
this.age=age;
this.id=id;
}
Student.prototype={
work:function(skill){
alert(this.name+"做"+skill+"开发相关的工作");
},
classId:"Java1班"
}
var stu1=new Student("李明",18,20151515);//得到的就是字面量对象
var stu2=new Student("王磊",18,20141000);//得到的就是字面量对象
console.log(stu2.work==stu1.work);//ture,节省了内存空间
stu1.work("Java");
stu2.work("PHP");
console.log(stu1.classId);//20151515
console.log(stu2.classId);//20141000
如果一个变量属于一个对象所有,那么该变量就可以称之为该对象的一个属性,属性一般是名词,用来描述事物的特征。
如果一个函数属于一个对象所有,那么该函数就可以称之为该对象的一个方法,方法是动词,描述事物的行为和功能。
new关键字
构造函数 ,是一种特殊的函数。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。
构造函数用于创建一类对象,首字母要大写。
构造函数要和new一起使用才有意义。
// Student 自定义构造函数
// 属性:name age sex score
// 方法:sayHi
function Student(name, age, sex, score) {
// 属性
this.name = name;
this.age = age;
this.sex = sex;
this.score = score;
// 方法
this.sayHi = function () {
console.log(this.name + ': hello');
}
}
var stu1 = new Student('lilei', 18, '男', 100);
var stu2 = new Student('hanmeimei', 17, '女', 100);
new在执行时会做四件事情
new会在内存中创建一个新的空对象
new 会让this指向这个新的对象
执行构造函数 目的:给这个新对象加属性和方法
new会返回这个新对象
this详解
JavaScript中的this指向问题,有时候会让人难以捉摸,随着学习的深入,我们可以逐渐了解
现在我们需要掌握函数内部的this几个特点
1. 函数在定义的时候this是不确定的,只有在调用的时候才可以确定
2. 一般函数直接执行,内部this指向全局window
3. 函数作为一个对象的方法,被该对象所调用,那么this指向的是该对象
4. 构造函数中的this其实是一个隐式对象,类似一个初始化的模型,所有方法和属性都挂载到了这个隐式对象身上,后续通过new关键字来调用,从而实现实例化
对象属性的使用:
1、可以用点符号访问对象属性值
2、也可以通过数组的方式,即用["属性名称"]
对象方法的使用:
可以使用对象名.方法名()来调用
遍历对象的属性
通过for..in语法可以遍历一个对象
var obj = {
name: '张三',
age: 18,
sex: true,
sayHi: function () {
console.log(this.name);
}
};
for(var key in obj) {
console.log(key + "==" + obj[key]);
}
删除对象的属性
function fun() {
this.name = 'mm';
}
var obj = new fun();
console.log(obj.name); // mm
delete obj.name;
console.log(obj.name); // undefined
基本类型又叫做值类型,复杂类型又叫做引用类型
值类型:简单数据类型,基本数据类型,在存储时,变量中存储的是值本身,因此叫做值类型。
Number String Boolean Null Undefined
引用类型:复杂数据类型,在存储是,变量中存储的仅仅是地址(引用),因此叫做引用数据类型。
Object Array
堆和栈
堆栈空间分配区别:
1、栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。
2、堆(操作系统): 存储复杂类型(对象),一般由程序员分配释放, 若程序员不释放,由垃圾回收机制回收。
注意:JavaScript中没有堆和栈的概念,此处我们用堆和栈来讲解,目的方便理解和方便以后的学习。
基本类型在内存中的存储:
复杂类型在内存中的存储:
基本类型作为函数的参数:
复杂类型作为函数的参数 :
// 下面代码输出的结果?
// 构造函数
function Person(name,age,salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
// 普通函数
function f1(person) { // person为形参
person.name = "lisi";
person = new Person("aa",18,10);
}
var p = new Person("zhangsan",18,1000);
console.log(p.name); // zhangsan
f1(p); // 把p对应的地址复制一份给person,person和p对应一个地址,那么修改地址对应的内容,会影响p
console.log(p.name); // lisi
//1.
var num1 = 10;
var num2 = num1; // num2 = 10;
num1 = 20;
console.log(num1); // 20
console.log(num2); // 10
//2.
var num = 50;
function f1(num) {
num = 60;
console.log(num);
}
f1(num); // 60
console.log(num); // 50