Object(对象)基础知识

对象

对象则用来存储键值对和更复杂的实体。
一个属性就是一个键值对(“key: value”),其中键(key)是一个字符串(也叫做属性名),值(value)可以是任何值。

创建对象

let user = new Object(); // “构造函数” 的语法
let user = {};  // “字面量” 的语法

众所周知,变量名不能是编程语言的某个保留字,如 “for”、“let”、“return” 等……
但对象的属性名并不受此限制:

let user = {
	name: "Ann", // 键 "name",值 "John"
	age: 18, // 键 "age",值 18
	"like music": true, // 多词属性名必须加引号
	0: "test", // 等同于 "0": "test"
	let: 1,
	for: 2,
	return: 666,
	class: "one"
}

点符号访问属性: obj.property

点符号要求 key 是有效的变量标识符。这意味着:不包含空格,不以数字开头,也不包含特殊字符(允许使用 $ 和 _)

console.log(user.name) // John
console.log(user.let + user.for + user.return) // 669
console.log(user.classs) // one

// 写入isAdmin属性
user.isAdmin = true
console.log(user)

// 移除isAdmin属性
delete user.isAdmin 
console.log(user)

方括号[]访问属性:obj["property"]。方括号允许从变量中获取键,例如 obj[key]

let user = {}
user.like music = true // 报错
user.0 = "test" // 报错

使用点符号访问报错图

对于多词属性,点符号访问会报错。
JavaScript 理解不了。它认为我们在处理 user.like,然后在遇到意外的 music 时给出了语法错误。
多词属性需要使用方括号[]访问。方括号[]可用于任意字符串。

// 设置
user["like music"] = true 
user[0] = "test"
user["0"] = "test"

let key = "circle"
user[key] = "圈圈" // 等同于 user["circle"] = "圈圈"

// 读取
console.log(user["like music"])

查是否存在给定键的属性,使用“in” 操作符: "key" in obj

请注意,in 的左边必须是 属性名。通常是一个带引号的字符串。

相比于其他语言,JavaScript 的对象有一个需要注意的特性:能够被访问任何属性。即使属性不存在也不会报错!
读取不存在的属性只会得到 undefined
但是,也有可能这个属性的值就是 undefined

let user = {
	age: undefined,
}

// 判断某个属性是否存在
console.log(user.name === undefined) // true, 表示没有这个属性,判断正确
console.log(user.age=== undefined) // true, 表示没有这个属性,判断错误

实际上,对象user里面存在age属性,只是age属性的值为 undefined
因此,为了精确判断对象里是否存在某个属性,建议使用in

console.log("name" in user) // false,不存在属性name
console.log("age" in user)  // true, 存在属性age

遍历对象:"key" in obj

for(let key in user) {
	console.log('key:' , key)
	console.log('value:', user[key])
}

对象方法,this

作为对象属性的函数被称为 方法

  • 存储在对象属性中的函数被称为“方法”。
  • 方法允许对象进行像 object.doSomething() 这样的“操作”。
  • 方法可以将对象引用为 this
let user = {
  name: "John",
  age: 30
};

user.sayHi = function() {
  console.log(`${this.name} say hello!`) // this指向user对象
};

user.sayHi(); // Hello!
  1. this” 不受限制
    在 JavaScript 中,this 关键字与其他大多数编程语言中的不同。JavaScript 中的 this 可以用于任何函数,即使它不是对象的方法。
    this 的值是在代码运行时计算出来的,它取决于代码上下文。
    例如,这里相同的函数被分配给两个不同的对象,在调用中有着不同的 “this” 值:
let user = { name: "John" };
let admin = { name: "Admin" };

function sayHi() {
  alert( this.name );  // 不会报错
}

// 在两个对象中使用相同的函数
user.f = sayHi;
admin.f = sayHi;

// 这两个调用有不同的 this 值
// 函数内部的 "this" 是“点符号前面”的那个对象
user.f(); // John(this == user)
admin.f(); // Admin(this == admin)

admin['f'](); // Admin(使用点符号或方括号语法来访问这个方法,都没有关系。)

这个规则很简单:如果 obj.f() 被调用了,则 thisf 函数调用期间是 obj。所以在上面的例子中 this 先是 user,之后是 admin

  1. 在没有对象的情况下调用:this == undefined
function sayHi() {
  alert(this);
}
sayHi(); // undefined

this 的值是在程序运行时得到的。

  • 一个函数在声明时,可能就使用了 this,但是这个 this 只有在函数被调用时才会有值。
  • 可以在对象之间复制函数。
  • 以“方法”的语法调用函数时:object.method(),调用过程中的 this 值是 object
    请注意箭头函数有些特别:它们没有 this。在箭头函数内部访问到的 this 都是从外部获取的。

构造函数

常规的 {...} 语法允许创建一个对象。
需要创建多个类似对象的时候,可以使用构造函数和 “new” 操作符来实现。
构造函数在技术上是常规函数。不过有两个约定:

  1. 它们的命名以大写字母开头。
  2. 它们只能由 “new” 操作符来执行。
function User(name) {
  this.name = name;
  this.isAdmin = false;
}

let user = new User("Jack");

alert(user.name); // Jack
alert(user.isAdmin); // false

当一个函数被使用 new 操作符执行时,它按照以下步骤:

  1. 一个新的空对象被创建并分配给 this。
  2. 函数体执行。通常它会修改 this,为其添加新的属性。
  3. 返回 this 的值。

换句话说,new User(...) 做的就是类似的事情:

function User(name) {
  // this = {};(隐式创建)

  // 添加属性到 this
  this.name = name;
  this.isAdmin = false;

  // return this;(隐式返回)
}

所以 new User("Jack") 的结果是相同的对象:

let user = {
  name: "Jack",
  isAdmin: false
};

现在,如果我们想创建其他用户,我们可以调用 new User("Ann")new User("Alice") 等。比每次都使用字面量创建要短得多,而且更易于阅读。

这是构造器的主要目的 —— 实现可重用的对象创建代码

构造器中的return

通常,构造器没有 return 语句。它们的任务是将所有必要的东西写入 this,并自动转换为结果。
但是,如果这有一个 return 语句,那么规则就简单了:

  • 如果 return 返回的是一个对象,则返回这个对象,而不是 this
  • 如果 return 返回的是一个原始类型,则忽略。
    换句话说,带有对象的 return 返回该对象,在所有其他情况下返回 this
function BigUser() {
  this.name = "John";
  return { name: "Godzilla" };  // <-- 返回这个对象,这里return通过返回一个对象,覆盖了this
}
console.log( new BigUser().name );  // Godzilla,得到了那个对象

function SmallUser() {
  this.name = "John";
  return;  // <-- 返回this
}
console.log( new SmallUser().name );  // John

构造器中的方法

function User(name) {
  this.name = name;
  
  this.sayHi = function() {
    alert( "My name is: " + this.name );
  };
}

let john = new User("John");

john.sayHi(); // My name is: John

// 相当于以下代码:
/*
john = {
   name: "John",
   sayHi: function() { ... }
}
*/
  1. 构造函数,或简称构造器,就是常规函数,但大家对于构造器有个共同的约定,就是其命名首字母要大写。
  2. 构造函数只能使用 new 来调用。这样的调用意味着在开始时创建了空的 this,并在最后返回填充了值的 this

练习

  1. 检查空对象
    写一个 isEmpty(obj) 函数,当对象没有属性的时候返回 true,否则返回 false
function isEmpty(obj) {
  for (let key in obj) {
    // 如果进到循环里面,说明有属性。
    return false;
  }
  return true;
}

let user= {}
console.log(isEmpty(user))
  1. 创建一个构造函数 Calculator,它创建的对象中有三个方法:
  • read() 使用 prompt 请求两个值并把它们记录在对象的属性中。
  • sum() 返回这些属性的总和。
  • mul() 返回这些属性的乘积。
function Calculator() {
  this.read = function() {
    this.a = +prompt('a?', 0);
    this.b = +prompt('b?', 0);
  };
  
  this.sum = function() {
  	return this.a + this.b;
  };

  this.mul = function() {
    return this.a * this.b;
  };
}

let calculator = new Calculator();
calculator.read();

console.log( "Sum=" + calculator.sum() );
console.log( "Mul=" + calculator.mul() );
  1. 创建一个构造函数 Accumulator(startingValue)
  • 将“当前 value”存储在属性 value 中。起始值被设置到构造器 startingValue 的参数。
  • read() 方法应该使用 prompt 来读取一个新的数字,并将其添加到 value 中。
    换句话说,value 属性是所有用户输入值与初始值 startingValue 的总和。
function Accumulator(startingValue) {
  this.value = startingValue;

  this.read = function() {
    this.value += +prompt('How much to add?', 0);
  };

}

let accumulator = new Accumulator(1);
accumulator.read();
accumulator.read();
console.log('accumulator.value:', accumulator.value);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值