JavaScript基础笔记3 (对象)
对象:
对象类似C语言结构体,{}内是Object的属性,一个属性就是一个键值对(“key: value”),其中键(key
)是一个字符串(也叫做属性名),值(value
)可以是任何值,包括Object,因此Object可以嵌套。
let user = new Object(); // “构造函数” 的语法
let user = {}; //{}内为空即为空属性字面量
//创建一个对象不一定要有初始属性,可以自由加入和删除属性。
//键是字符串类型,一般不带空格,如果带空格只需要把空格括在引号里:
let user = {
name: "John",
age: 30,
"likes birds": true
};
//调用一个对象的属性可以用".",也可以用[],但是[]内必须是String类型,但是键出了对象之后解释器就不认识了,因此需要将其值用另一个变量存储,或者直接加引号。
let N = "name";
console.log(user[N]); //John
console.log(user["na"+"me"]); //John
console.log(user["likes birds"]); //true
console.log(user.N); //undefined 虽然N和键name都是字符串,但是点还是不能这么用
然后任何Object类型的变量名都可以相互赋值,说白了JavaScript里所有的变量名只是个浮动的指针而已,甚至Object和function之间都能相互赋值:
let you = { age:18, height:114, neko:()=>alert("qwq") }; //属性里可以有函数
let me = { a:114514, b:1919810, c:"qwq" };
you = me;
you.neko(); //error you变成me之后,原有的neko属性没了
function add(A,B) { return A+B; }
you = add;
console.log(you(3,4)); //7 you已经成为了function
add = me;
console.log(add.a); //114514 add已经成为了Object
计算属性:
在花括号字面量中键用[]括起来,可以将[]里变量内容作为键,而不是变量名作为键。
let fruit = prompt("Which fruit to buy?", "apple");
let bag = {
[fruit]: 5, // 属性名是从 fruit 变量中得到的
};
alert( bag.apple ); // 5 如果 fruit="apple"
//如果输入的不是apple,那就没有这个属性,会弹出undefined
在实际开发中,我们通常用已存在的变量当做属性名。
function makeUser(name, age) { //通过几个已知的变量生成Object
return {
name: name,
age: age,
};
}
let user = makeUser("John", 30);
//如果你希望变量名和属性相同,可以将键和值合在一起(属性值简写):
function makeUser(name, age) {
return {
name,
age,
};
}
除了一个名为__proto__
的属性,其他所有的变量名都会被当做String处理,不需要担心键名与关键词冲突:
let obj = {
for: 1,
let: 2,
return: 3,
0: 0 //即使是数字也会被转成"0"字符串
};
console.log(obj.return); //3 不会报错,正常使用
in关键词用于计算前者(String)是否在后者(Object)中。
for循环中使用let in结构,可以遍历对象中的所有键,由于key不是关键词,方便用于变量名:
let you = {
name,
age:30
};
let a = "name";
console.log(a in you); //返回Boolean型
for(let key in you) {
console.log(key,you[key]); //name age 30
}
//在遍历时,如果属性为非负整数字符串,那么会优先遍历并排序遍历
//这个非负整数必须严格按只有数字字符组成,空格,正负号,小数点都不能存在
//JavaScript教程给出的例子:想要按数字属性给入的顺序输出,属性名加+号即可,输出时若不想保留+号可以再把字符串转成Number类型
let codes = {
"+49": "Germany",
"+41": "Switzerland",
"+44": "Great Britain",
// ..,
"+1": "USA"
};
for (let code in codes) {
alert( +code ); // 49, 41, 44, 1
}
方法:
作为对象属性的函数被称为方法。定义属性时方法可以简写:
user = {
sayHi: function() {
alert("Hello");
},
};
let user = {
sayHi() { alert("Hello"); }, //简写,即忽略掉冒号和function
};
let user = {
sayHi : ()=>alert("Hello");, //一定程度上也等同于这个
};
与C++中的结构体类似,如果方法需要访问对象内的属性时,可以使用this关键字:
let user = {
name: "John",
age: 30,
sayHi() { alert(this.name); }
};
//如果函数不是某个对象的方法,使用this也不会报错。而当某个对象引入了这个函数作为方法,this的值就会成为引入它的对象
let user = { name: "John" };
let admin = { name: "Admin" };
function sayHi() {
alert( this.name );
}
user.f = sayHi;
admin.f = sayHi;
sayHi(); // 直接调用的话什么都不会输出,但是也不会报错
user.f(); // John (this == user)
admin.f(); // Admin(this == admin)
//this类型天然是Object,即使函数不是对象的方法
function thistype() {
alert( typeof this);
}
thistype(); //object
一个易错点:
//this的具体值只会在调用时赋值,若调用时外层为函数,this会赋值为函数的this。
//JavaScript教程的例题:
function makeUser() {
return {
name: "John",
ref: this
};
}
let user = makeUser();
alert( user.ref.name ); // Error: Cannot read property 'name' of undefined
//ref第一次调用为makeUser函数调用,其值为函数的this(undefined),而不是user的this
//正确代码如下:
function makeUser() {
return {
name: "John",
ref() {
return this;
}
};
}
let user = makeUser();
alert( user.ref().name ); // John
//这样this在调用时是ref函数的对象,也就是user自己了。