1. 对象
1. 创建对象
// 创建对象
let obj = {...} //字面量创建对象
let obj = new Object ( ); // “构造函数” 的语法
2. 属性
let user = { // 一个对象
name: "John", // 键 "name",值 "John"
age: 30 // 键 "age",值 30
};
// 读取文件的属性:
alert( user.name ); // John
alert( user.age ); // 30
//user['age'] //动态写法
// 属性可以是任何类型
//1. 添加一个布尔型
user.isAdmin = true;
//2. 删除属性 delete
delete user.age;
//3. 多词属性名
let user = {
name: "John",
age: 30,
"likes birds": true // 多词属性名必须加引号
};
方括号
对于多词属性 .不够用
let user = {};
// 设置
user["likes birds"] = true;
// 读取
alert(user["likes birds"]); // true
// 删除
delete user["likes birds"];
//方括号同样提供了一种可以通过任意表达式来获取属性名的方法
let user = {
name: "John",
age: 30
};
let key = prompt("What do you want to know about the user?", "name");
// 访问变量
alert( user[key] ); // John(如果输入 "name")
检查是否存在给定键的属性
let user = { name: "John", age: 30 };
alert( "age" in user ); // true,user.age 存在
alert( "blabla" in user ); // false,user.blabla 不存在。
“for…in” 循环
为了遍历一个对象的所有键(key),可以使用一个特殊形式的循环:for…in。这跟我们在前面学到的 for循环是完全不一样的东西。
for (key in object) {
// 对此对象属性中的每个键执行的代码
}
let user = {
name: "John",
age: 30,
isAdmin: true
};
for (let key in user) {
// keys
alert( key ); // name, age, isAdmin
// 属性键的值
alert( user[key] ); // John, 30, true
}
//同样,我们可以用其他属性名来替代 key。例如 "for(let prop in obj)" 也很常用。
2. 构造函数
构造函数:其实也是函数,只不过构造函数一般用于和new搭配使用,创建对象
1.命名规则
它们的命名以大写字母开头。
它们只能由 “new” 操作符来执行。
当一个函数被使用 new 操作符执行时,它按照以下步骤:
一个新的空对象被创建并分配给 this。
函数体执行。通常它会修改 this,为其添加新的属性。
返回 this 的值。
function User(name) {
// this = {};(隐式创建)
// 添加属性到 this
this.name = name;
this.isAdmin = false;
// return this;(隐式返回)
}
//所以 new User("Jack") 的结果是相同的对象:
let user = {
name: "Jack",
isAdmin: false
};
构造器的主要目的 —— 实现可重用的对象创建代码。
注意:如果构造函数不需要参数,那么可以省略小括号
let user = new User; // <-- 没有参数
// 等同于
let user = new User();
// 内置构造函数:Object,创建对象
// let obj = new Object();
// console.log( obj );
// 添加东西
// obj.uname = '阿飞';
// obj.age = 22;
// obj.fei = function () {
// console.log('方法');
// };
// obj.chi = function () {
// console.log('吃');
// }
// console.log( obj );
// 自定义构造函数
// 建议:所有构造函数的首字母大写
// 构造函数里面this指向当前实力对象
function Person (uname, age, sex) {
// 设置属性
this.uname = uname;
this.age = age;
this.sex = sex;
this.eat = function () {
console.log('吃饭');
};
this.sing = function () {
console.log('唱歌');
}
}
// 一般如何使用
// 实例化对象
let o = new Person('张三丰', 22, '男');
console.log( o );
let o1 = new Person('阿飞', 21, '男');
console.log( o1 )
instanceof
// instanceof:用于判断一个对象是否是另外一个构造函数的实例对象
// 定义构造函数
function C(){}
function D(){}
var o = new C();
o instanceof C; // true,因为 Object.getPrototypeOf(o) === C.prototype
o instanceof D; // false,因为 D.prototype 不在 o 的原型链上
o instanceof Object; // true,因为 Object.prototype.isPrototypeOf(o) 返回 true
C.prototype instanceof Object // true,同上
实例成员就是在构造函数内部添加的成员,只能由实例化的对象来访问
function Star(uname,age){
this.uname = uname;
this.age = age;
this.sing = function(){
console.log("我会唱歌");
}
}
var ldh = new Star('刘德华',18);//创建实例化对象
console.log(ldh.uname);//用实例化对象ldh访问uname 正确
ldh.sing();//用实例化对象ldh访问sing() 正确
console.log(Star.uname);//用构造函数访问uname 报错
静态成员就是在构造函数本身上添加的成员,只能由构造函数本身来访问
function Star(uname,age){
this.uname = uname;
this.age = age;
this.sing = function(){
console.log("我会唱歌");
}
}
ldh = new Star('刘德华',18);
Star.sex = '男';//创建静态成员
console.log(Star.sex);//通过构造函数本身访问sex 正确
console.log(ldh.sex);//通过实例化对象访问 报错
引用类型
对象与原始类型的根本区别之一是,对象是“通过引用”存储和复制的,而原始类型:字符串、数字、布尔值等 —— 总是“作为一个整体”复制。
当一个对象变量被复制 —— 引用被复制,而该对象自身并没有被复制。
// 变量传递给另外一个变量,称为数据传递
// 值传递:会把数据复制一份传递,(简单类型)
// 引用传递:会把数据地址复制一份传递,(引用类型)
let user = { name: "John" };
let admin = user; // 复制引用
正如你所看到的,这里仍然只有一个对象,但现在有两个引用它的变量。
我们可以通过其中任意一个变量来访问该对象并修改它的内容:
let user = { name: 'John' };
let admin = user;
admin.name = 'Pete'; // 通过 "admin" 引用来修改
alert(user.name); // 'Pete',修改能通过 "user" 引用看到
- 通过引用来比较
let a = {};
let b = a; // 复制引用
alert( a == b ); // true,都引用同一对象
alert( a === b ); // true
而这里两个独立的对象则并不相等,即使它们看起来很像(都为空):
案例1:
let a = {};
let b = {}; // 两个独立的对象
alert( a == b ); // false
let n = 10;
let m = 11;
function fn (a, b) {
// a = n
// b = m
a = 100;
b = 200;
}
fn(n, m);
console.log(n, m); // 10 11
// 相当于n和m传给了a 和 b 导致a 和 b 也指向了 n 和m指向的地址
案例2:
let o = {uname : '张三丰', age : 22, sex : '男'};
function fun (obj) {
// obj = o
obj.uname = '李寻欢';
}
fun(o);
console.log(o); //uname 变成了 李寻欢
// 相当于实参o传给了形参obj o和obj都指向了同一块地址 obj.uname改变了 o,uname也会改变
案例3:
let arr = ['张飞', '关羽', '赵云'];
function fn (ary) {
ary[0] = '张辽';
}
fn(arr);
console.log(arr); //['张辽', '关羽', '赵云']
Object:创建普通对象的构造函数
let obj = new Object( {uname : '阿飞', age : 22, sex : '男'} );
console.log(obj);
//{uname: '阿飞', age: 22, sex: '男'}
// Object:创建普通对象的构造函数
let obj = new Object( {uname : '阿飞', age : 22, sex : '男'} );
console.log(obj);
// Object.keys():获取对象的所有键
let re = Object.keys(obj)
console.log( re );
// Object.values()获取对象的索引值
let re1 = Object.values(obj);
console.log(re1);
Object.prototype 是构造出来的对象的原型。
// Object.getPrototypeOf() 方法返回指定对象的原型(内部[[Prototype]]属性的值)。
Object.prototype === Object.getPrototypeOf( obj ); // true
Object.prototype === Object.getPrototypeOf( {} ); // true
数组
// 任何一个属性都是Array构造函数的实例化对象
// 字面量
let arr = [1, 2, 3];
// Array构造函数
// let ary = new Array(1, 2, 3);
// console.log( ary );
console.log( arr instanceof Array ); //true
// concat:用于拼接为新数组
let arr = [1, 2, 3];
let ary1 = ['a', 'b', 'c', 'd'];
let ary2 = [11, 222, 333];
let reArr = arr.concat(ary1, ary2, '张飞', '关羽', '赵云');
console.log(reArr);
// join():用于连接数组的每个元素成为字符串
let arr = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
let str = arr.join('');
console.log(str); //abcdefgh
// reverse:翻转数组顺序
let arr = [1, 2, 3];
let re = arr.reverse();
console.log(re);
//[3,2,1]
// indexOf:查找某个元素在数组中首次出现的索引位置,找不到就是返回-1
let arr = ['a', 'b', 'c', 'd', 'a', 'b', 'f'];
let re = arr.indexOf('m');
console.log(re); //-1
// lastIndexOf:查找某个元素在数组中尾次出现的索引位置,找不到就返回-1
let re = arr.lastIndexOf('b');
console.log(re); //5
// // sort:排序
let arr = [3, 16, 22, 66, 123, 99];
// // 正序排列:
let re = arr.sort(function (a, b) {return a - b;});
// 倒序排列
// let re = arr.sort(function (a, b) {return b - a;});
console.log( re );
// 判断一个值是否是数组
// Array.isArray();
let a = [1, 2, 3];
let re = Array.isArray(a);
console.log(re); //true
// 把伪数组转换为真数组
// Array.from(伪数组)
// 特别注意:要想把伪数组转换为真数组必须有length属性
let o = {
0 : 'a',
1 : 'b',
2 : 'c',
3 : 'd',
4 : 'e',
5 : 'f',
6 : 'h',
length : 4,
}
let ary = Array.from(o);
console.log( ary ); // ['a', 'b', 'c', 'd']
伪数组转为真数组练习
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ul>
<script type="text/javascript">
// let lis = document.querySelectorAll('li');
// // console.log(lis);
// let arr = Array.from(lis);
// arr.pop();//移除最后一个
// console.log(arr);
function fn () {
// console.log(arguments);
let ary = Array.from(arguments);
ary.pop();
console.log(ary);
}
fn(1, 2, 3, 'a', 'b', 'c');
// [1, 2, 3, 'a', 'b']
</script>
forEach() 遍历数组
// forEach:用于遍历数组
let arr = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
arr.forEach( function (item, index, o) {
// 第一个参数:代表数组的每一项(每个元素)
// 第二个参数:代表数组的每一项的索引值(索引值)
// 第三个参数:代表当前数组本身
console.log(item, index, o);
} );
// for (let i = 0; i < arr.length; i++) {
// arr[i]
// }
let arr = [
{uname :'阿飞', age : 22, sex : '男'},
{uname :'张三丰', age : 23, sex : '男'},
{uname :'李寻欢', age : 21, sex : '男'},
{uname :'张三丰1', age : 23, sex : '男'},
{uname :'李寻欢1', age : 21, sex : '男'},
{uname :'张三丰2', age : 23, sex : '男'},
{uname :'李寻欢2', age : 21, sex : '男'},
{uname :'张三丰2', age : 23, sex : '男'},
{uname :'李寻欢2', age : 21, sex : '男'},
];
arr.forEach( item => {
console.log(`姓名:${item.uname},年龄${item.age},性别${item.sex}`);
} );
正则构造函数
// 字面量:
// let reg = /abc/;
// 构造函数:
let reg1 = new RegExp(/abc/);
总结
// 解构赋值:
// 数组:let [a, b, c] = [值一一对应]
// 对象:let {变量名} = {键值对}
// 面向过程,面向对象
// 创建对象:
// 字面量:let obj1 = {键值对};
// 构造函数:let obj2 = new Object();
// 自定义构造函数:let obj3 = new 构造函数();
// 成员:
// 静态成员:构造函数身上直接添加的成员,只能由构造函数使用
// 实例成员:构造函数内部的成员叫实例成员,只能由实例对象使用
// 引用类型:
// 变量赋值给变量
// 值传递:把数据复制一份传递,(简答类型)
// 引用传递:把数据地址复制一份传递,(引用类型)
// Object构造函数:用于创建普通对象
// Object.keys
// Object.values
// Array构造函数:用于创建数组对象
// concat、join、reverse、indexOf、lastIndexOf、sort、
// Array.isArray、Array.from
// forEach
// RegExp构造函数;用于创建正则对象