本地对象
与宿主无关,无论在浏览器还是服务器中都有的对象,就是ECMAScript标准中定义的类(构造函数)
在使用过程中需要我们手动new创建
例如:Boolean、Number、String、Array、Function、Object、Date、RegExp等
内置对象
与宿主无关,无论在浏览器还是服务器中都有的对象
ECMAScript已经帮我们创建好的对象
在使用过程中无需我们动手new创建
例如:Global、Math、JSON
宿主对象
什么是宿主?
宿主就是指JavaScript运行环境,js可以在浏览器中运行,也可以在服务器上运行(nodejs)
对于嵌入到网页中的js来说,其宿主对象就是浏览器,所以宿主对象就是浏览器提供的对象
包含:Window和Docuument等
所有的DOM和BOM对象都属于宿主对象
一、概述
1.1 面向对象和面向过程的区别
面向过程:
强调的是功能行为
关注的是解决问题需要哪些具体的步骤
面向对象:
将功能封装进对象、强调具备了功能的对象
关注的是解决问题需要哪些对象
1.2 概述
描述: 大括号({})定义的无序的数据集合,由键值对构成,键与值之间用冒号分隔,大括号末尾要使用分号表示对象定义结束
对象被认为是某个特定引用类型的实例
语法 : var obj={key1:value1,key2:value2…};
每队键值对之间用逗号隔开
键名:
-
键名也被称为属性(property),对象的所有属性都是字符串,所以加不加引号都可以
-
如果属性不符合标识符的条件(比如第一个字符为数字,或者含有空格或运算符),则必须加上引号
键值:
- 对象的键值可以是任何数据类型
<script>
var obj = {
name: 'zhangsan',
age: 18,
sex: 'male',
//方法
ability: function eat() {
console.log('我要吃饭饭');
}
};
console.log(obj.age); //18
console.log(obj.name); //zhangsan
obj.ability(); //我要吃饭饭
console.log(obj.height);// undefined
</script>
1.3 对象是引用类型
不同对象在堆中的地址不同
<script>
var obj1 = {
a: 1,
b: 2,
c: 3
};
var obj2 = {
a: 1,
b: 2,
c: 3
};
console.log(obj1 == obj2); // false
console.log(obj1 === obj2); // false
console.log({} == {}); // false
console.log({} === {}); // false
</script>
1.4 创建对象的几种方式
直接使用大括号创建对象 -->对象字面量/对象直接量
使用new命令生成一个Object对象的实例 -->构造函数
使用Object.creat()方法创建对象 -->
<script>
//通过对象字面量/对象直接量创建对象
var obj1 = {};
let obj = {
name: "lnj",
age: 33,
say: function () {
console.log("hello world");
}
};
//通过Object()创建对象
var obj2 = new Object();
obj2.name = "zhangsan";
obj2.age = 12;
// 方法
obj.say = function () {
console.log("hello world");
}
console.log(obj2);
//利用构造函数自定义对象
function Person() {
}
var person1 = new Person();
//
var obj3 = Object.create(null);
</script>
1.5 函数和方法的区别
函数就是没有和其它的类显示的绑定在一起的, 我们就称之为函数
方法就是显示的和其它的类绑定在一起的, 我们就称之为方法
函数和方法的区别:
函数可以直接调用, 但是方法不能直接调用, 只能通过对象来调用
function demo() {
// console.log("hello demo");
console.log(this);
}
// demo();
window.demo();
函数内部的this输出的是window
方法内部的this输出的是当前调用的那个对象
如果方法变为箭头函数后this输出的是window
let obj = {
names: "lwj",
test: function () {
// console.log("hello test");
console.log(this.names); // lwj
console.log(this['names']); // lwj
}
}
// test();
obj.test();
无论是函数还是方法, 内部都有一个叫做this的东东
- this是什么? 谁调用了当前的函数或者方法, 那么当前的this就是谁
1.6 对象嵌套
- 一个复合的数据如果存储的是同类型的数据,则用数组存(注意:这里的同类型指的是逻辑上的同类型)
- 如果类型不同则用对象进行存储数据,对象可以通过不同的属性名标识不同的属性值
/**
* 对象嵌套
*/
const wtxy = {
xyName: "梧桐学苑",
boss: "lwj",
address: "深圳市光明区光明大道xxx号xxx楼",
school: [
{
name: "成都校区",
address: "成都市高新区天府大道xxx号xxx楼",
boss: "成华",
major: [
{
name: "java全栈",
leader: "赵柳",
count: 320,
classes: [
{
name: "1期",
teacher: "赵丽颖",
studentsInfo: [
{
name: "张三",
age: 20,
history: "硕士"
},
{
name: "王五",
age: 18,
history: "博士"
},
{
name: "赵丽",
age: 22,
history: "本科"
}
]
}
]
},
{
name: "web前端",
leader: "刘涛",
count: 440,
classes: [
{
name: "12期",
teacher: "赵颖",
studentsInfo: [
{
name: "刘明",
age: 30,
history: "硕士"
},
{
name: "张桃",
age: 24,
history: "博士"
},
{
name: "杜娆",
age: 21,
history: "本科"
}
]
}
]
}
]
},
{
name: "重庆校区",
address: "重庆市渝北区育人大道xxx号xxx楼",
boss: "李四",
major: [
{
name: "python全栈",
leader: "申郝",
count: 420,
classes: [
{
name: "8期",
teacher: "国明轩",
studentsInfo: [
{
name: "晓丽",
age: 20,
history: "大专"
},
{
name: "胡敏",
age: 18,
history: "本科"
},
{
name: "刘德华",
age: 28,
history: "博士"
}
]
}
]
},
{
name: "UI设计师",
leader: "向涛",
count: 150,
classes: [
{
name: "2期",
teacher: "舒国",
studentsInfo: [
{
name: "陆刑",
age: 19,
history: "本科"
},
{
name: "代凤",
age: 24,
history: "硕士"
},
{
name: "江娆",
age: 21,
history: "博士"
}
]
}
]
}
]
},
{
name: "武汉校区",
address: "武汉市街口区路北大道xxx号xxx楼",
boss: "成华",
major: [
{
name: "java全栈",
leader: "孙铭2",
count: 620,
classes: [
{
name: "19期",
teacher: "郭志坚",
studentsInfo: [
{
name: "陆志强",
age: 20,
history: "高中"
},
{
name: "黄岩",
age: 24,
history: "硕士"
},
{
name: "李达",
age: 28,
history: "博士"
}
]
}
]
},
{
name: "c#工程师",
leader: "候想",
count: 490,
classes: [
{
name: "20期",
teacher: "郭阳",
studentsInfo: [
{
name: "向阳",
age: 25,
history: "硕士"
},
{
name: "胡烈拉",
age: 29,
history: "博士"
},
{
name: "罗杰",
age: 21,
history: "本科"
}
]
}
]
}
]
}
]
};
// 1.输出公司的总 boss 的名称
console.log(wtxy.boss);
// 2.输出所有分校的名称
for(let i = 0; i < wtxy.school.length; i++){
console.log(wtxy.school[i].name);
}
// 3.输出每一个校区的专业名称
for(let i = 0; i < wtxy.school.length; i++){
for(let j = 0; j < wtxy.school[i].major.length; j++){
console.log(wtxy.school[i].name + ":" + wtxy.school[i].major[j].name);
}
}
1.7 对象的遍历(for in)
// 对象的遍历
// for in
const obj = {
name: 'ls',
age: 18,
sex: '男'
}
for(let k in obj) {
console.log(k); // 得到属性名
console.log(obj[k]);
}
二 、对象的读写属性
2.1 对象属性的读取
- 描述: 实际是获取对象属性所对应的属性值
注意:
- 需要注意的是,使用方括号读取对象属性的时候需要加引号
- 访问对象中不存在的属性时,不会报错而是返回undefined
<script>
var obj = {
sname: '贝西',
height: 170
}
//点运算符
console.log(obj.sname); //贝西
console.log(obj.height); //170
console.log(obj.age); //undefined
//方括号运算符
console.log(obj['sname']); //贝西
</script>
2.2 对象属性的写入
- 描述: 点运算符和中括号运算符都能够给对象的属性和方法赋值,无论属性是否存在(修改属性值)
<script>
var obj = {
name: '贝西',
height: 170
};
//修改(改)
obj.name = '张先生';
obj['height'] = '170cm';
console.log(obj); // {name: "张先生", height: "170cm"}
//添加(增)
obj.sex = 'male';
obj['age'] = 22;
console.log(obj); // {name: "张先生", height: "170cm", sex: "male", age: 22}
// 对象属性的删除(删)
delete obj.sex;
console.log(obj); // {name: "张先生", height: "170cm", age: 22}
// 查
console.log(obj.name); // 张先生
</script>
2.3 总结
【中括号】和【点符号】到底有什么区别呢?
- 中括号运算符总是能代替点运算符。但点运算符却不一定能全部代替中括号运算符
- 中括号运算符可以用字符串变量的内容作为属性名。点运算符不能
<script>
var obj = {
name: '贝西',
height: 170
};
var str = 'height';
console.log(obj.str); //undefined
console.log(obj[str]); //170
</script>
- 中括号运算符可以用纯数字为属性名。点运算符不能
<script>
var obj = {};
obj[0] = 'aa';
obj[1] = 'bb';
console.log(obj); //{0: "aa", 1: "bb"}
</script>
- 中括号运算符可以用js的关键字和保留字作为属性名。点运算符不能
<script>
var obj = {};
obj.document = 'sxt';
obj[document] = 'hello';
console.log(obj); //{document: "sxt", [object HTMLDocument]: "hello"}
</script>
总结:
- 常规情况下使用第一种访问对象属性(即 .)
- 当属性名称是用一个变量来表示时,必须使用第二种方式,对象名.[变量]=>访问的是变量的值对应的属性
三、对象属性操作
3.1 Object.keys()
- 描述:用来获取对象中所有的属性并构成数组返回
- 语法:Object.keys(对象)
- 【Object.keys()】是一个整体,调用的时候必须整体调用
<script>
var obj = {
name: '贝西',
height: 170,
sex: 'male'
}
var result = Object.keys(obj);
console.log(result); //["name", "height", "sex"]
</script>
3.2 delete
- 描述:删除对象的一个属性(实际删除的是一对键值对)
- 语法:delete obj.property
- 删除成功返回 true;反之返回 false
- 但是,如果删除一个不存在的属性,delete 不会报错,反而会返回 true
<script>
var obj = {
name: '贝西',
height: 170,
sex: 'male'
}
console.log(obj); //{name: "贝西", height: 170, sex: "male"}
var result = delete obj.sex;
console.log(obj); //{name: "贝西", height: 170}
console.log(result); //true
var result2 = delete obj.age;
console.log(result2); //true
</script>
3.3 in
- 描述:检查对象是否包含一个属性
- 语法: key in obj
<script>
var obj = {
name: '贝西',
height: 170,
sex: 'male',
address: undefined
};
console.log(obj.height); //170
console.log(obj.age); //undefined
console.log('name' in obj); //true
console.log('age' in obj); //false
console.log('address' in obj); //true
</script>
3.4 for in
- 描述:快速遍历
- 语法: for(var pro in obj){…}
- 注意:循环变量pro表示的是对象的属性名,并不表示属性的值!
<script>
var obj = {
name: '贝西',
height: 170,
sex: 'male'
};
for (var pro in obj) {
//obj.pro 获取对象中的属性
//obj[pro] 获取对象中属性的内容即属性值
//取出obj对象中名为当前遍历到的名称的属性或者方法的取值
console.log(obj[pro]); // 贝西 170 male
//console.log(obj.pro); //取出obj对象中名为pro的属性的取值
}
</script>
3.5 with()(了解)
- 描述:同时操作一个对象的多个属性
- 语法:with(obj){
key1 = value1;
key2 = value2;
}
<script>
var obj = {
name: '贝西',
height: 170,
};
with(obj) {
name = '贾先生';
height = '170cm';
age = 22;
}
console.log(obj); //{name: "贾先生", height: "170cm"}
</script>
四、 对象的引用
- 描述:如果一个变量指向一个对象,那么这个变量就称为这个对象的引用
- 注意:对一个对象的对象引用做出的修改,会影响整个对象的状态。
<script>
var obj1 = {
name: '张三',
age: 18
};
var obj2 = obj1;
var obj3 = obj1;
obj1.name = '贝西';
console.log(obj2);
console.log(obj3);
obj2.age = 24;
console.log(obj1);
console.log(obj2);
console.log(obj3);
</script>
五、工厂函数
工厂函数就是专门用于创建对象的函数
function createPerson (myName,myAge) {
let obj = new Object();
obj.name=myName;
obj.age=myAge;
obj.say=function () {
console.log("hi");
}
return obj;
}
let obj1=createPerson("zs",14);
let obj2=createPerson("li",18);
console.log(obj1);
console.log(obj2);
六、构造函数
构造函数和工厂函数一样,都是用于创建对象的
构造函数本质上是工厂函数的简写
构造函数的函数名称首字母必须大写
构造函数只能通过new关键字来调用
function Person(myName,myAge) {
// let obj=new Object(); 系统自动添加的
// let this = obj; 系统自动添加的
this.name=myName;
this.age=myAge;
this.say=function () {
console.log("hi");
}
// return this; 系统自动添加的
}
/*
*当 new Person("zs",14); 时系统做了什么?
* 1.会在构造函数中自动创建一个对象
* 2.会自动将刚才创建的对象赋值给this
* 3.会在构造函数最后添加 return this;
*/
let obj1=new Person("zs",14);
let obj2=new Person("li",18);
console.log(obj1);
console.log(obj2);
示例1:
function Person(myName,myAge) {
// let obj=new Object(); 系统自动添加的
// let this = obj; 系统自动添加的
this.name=myName;
this.age=myAge;
this.say=function () {
//方法中的this是谁调用就是谁
console.log("hi");
console.log(this.name,this.age);
}
// return this; 系统自动添加的
}
/*
*当 new Person("zs",14); 时系统做了什么?
* 1.会在构造函数中自动创建一个对象
* 2.会自动将刚才创建的对象赋值给this
* 3.会在构造函数最后添加 return this;
*/
let obj1=new Person("zs",14);
let obj2=new Person("li",18);
console.log(obj1);
console.log(obj1.name);
console.log(obj2);
obj1.say();
//存储空间不同
console.log(obj1.say===obj2.say);//flase
示例2:
/*
* 降低了阅读的可读性
*污染了全局的命名空间
*/
function mySay() {
console.log("hi");
}
function Person(myName,myAge) {
// let obj=new Object(); 系统自动添加的
// let this = obj; 系统自动添加的
this.name=myName;
this.age=myAge;
this.say=mySay;
// return this; 系统自动添加的
}
/*
*当 new Person("zs",14); 时系统做了什么?
* 1.会在构造函数中自动创建一个对象
* 2.会自动将刚才创建的对象赋值给this
* 3.会在构造函数最后添加 return this;
*/
let obj1=new Person("zs",14);
let obj2=new Person("li",18);
console.log(obj1.say===obj2.say);//true
示例3:
let fn={
test:function mySay() {
console.log("hi");
}
}
function Person(myName,myAge) {
// let obj=new Object(); 系统自动添加的
// let this = obj; 系统自动添加的
this.name=myName;
this.age=myAge;
this.say=fn.test;
// return this; 系统自动添加的
}
/*
*当 new Person("zs",14); 时系统做了什么?
* 1.会在构造函数中自动创建一个对象
* 2.会自动将刚才创建的对象赋值给this
* 3.会在构造函数最后添加 return this;
*/
let obj1=new Person("zs",14);
let obj2=new Person("li",18);
console.log(fn.test===fn.test);//true
示例4:(重点)
function Person(myName,myAge) {
// let obj=new Object(); 系统自动添加的
// let this = obj; 系统自动添加的
this.name=myName;
this.age=myAge;
// return this; 系统自动添加的
}
Person.prototype = {
say:function () {
console.log("hi");
}
}
/*
*当 new Person("zs",14); 时系统做了什么?
* 1.会在构造函数中自动创建一个对象
* 2.会自动将刚才创建的对象赋值给this
* 3.会在构造函数最后添加 return this;
*/
let obj1=new Person("zs",14);
let obj2=new Person("li",18);
console.log(obj1.say===obj2.say);//true
七、伪数组(类数组)
由于对象有[]访问属性这种语法,当我们故意将属性名从0开始递增的时候,在给对象添加一个length属性,此时我们可以使用操作数组的方式去操作对象,此时的对象就好像一个数组一样,这就是伪数组,但是区别是对象是不具备数组特有的函数的
//自定义一个对象实现伪数组
var arr={
length:0
};
示例1:
/**
* 对象中的函数可以通过 this 访问该对象的属性(箭头函数除外)
* 使用伪对象模拟数组:
* 1.对象必须使用数字(索引)作为属性名称来存储数据
* 2.对象必须有一个 length 属性
* 3.实现 push 函数,新属性名称为 length 的值
* 4.实现unshfit函数
* 5.实现pop函数
* 6.实现shift函数
* 7.实现sort函数
* 8.实现indexOf函数
* 9.实现lastIndexOf函数
* 10.实现join函数
* 11.实现slice 返回真数组
*/
const arr = {
length: 0,
// 1. 遍历对象里的属性
show: function () {
for (let i = 0; i < this.length; i++) {
console.log(this[i]);
}
},
// 2.实现push函数
push: function (data) {
// this 代表的是当前对象
// this[this.length] = data;
// 等价于
arr[arr.length] = data;
this.length++;
},
// 3.实现 unshift 函数
unshift: function (data) {
// 数据后移
for (let i = this.length; i > 0; i--) {
this[i] = this[i - 1];
}
// 将 0 号属性赋值给 data
this[0] = data;
this.length++;
},
// 4. 实现 pop 函数
pop: function () {
// 取出目前最后一个数据
let last = this[this.length - 1];
// 使用 delete 关键字删除属性
delete this[--this.length];
return last;
},
// 5.实现 shift 函数--从头部取出数据
shift: function () {
/*
将后面的数据向前移
第一个数据就会保存到变量 first 里
删除最后一个数据
*/
let first = this[0];
// 数据前移
for (let i = 0; i < this.length - 1; i++) {
this[i] = this[i + 1];
}
delete this[--this.length]; // 删掉最后一个数据
return first;
},
// 6.实现 sort 函数(选择排序)
sort: function (callback) {
for (let i = 0; i < this.length - 1; i++) {
for (let j = i + 1; j < this.length; j++) {
if (callback(this[i], this[j]) > 0) {
let temp = this[i];
this[i] = this[j];
this[j] = temp;
}
}
}
},
// 7.实现 indexOf 函数
indexOf: function (data) {
let index = -1;
for (let i = 0; i < this.length; i++) {
if (this[i] == data) {
index = i;
return index;
}
}
if (index == -1) {
return index;
}
},
// 8.实现 lastIndexOf 函数
lastIndexOf: function (data) {
let index = -1;
for (let i = this.length - 1; i >= 0; i--) {
if (this[i] == data) {
index = i;
return index;
}
}
if (index == -1) {
return index;
}
},
// 9.实现 join 函数
join: function (seprator) {
if (!seprator) { // !str ==> == undefined
seprator = ",";
}
let str = '' + this[0];
for(let i = 1; i < this.length; i++){
str += seprator + this[i];
}
return str;
},
// 10. 实现 slice 函数
slice: function (num1, num2) {
let newArr = [];
if (num2 > num1 && num1 > 0 && num2 > 0) {
for (let i = num1; i < num2; i++) {
newArr[newArr.length] = this[i];
}
} else if (num1 > 0 && num2 < 0) {
for (let i = num1; i < this.length + num2; i--) {
newArr[newArr.length] = this[i];
}
} else if (num1 < 0 && num2 < 0) {
for (let i = this.length + num1; i > this.length + num2; i--) {
newArr[newArr.length] = this[i];
}
}
return newArr;
},
// 11.实现 splice 函数
// index 需要操作的位置
// number 需要删除的数量
// data 要替换的数据
splice: function (index, number, data) {
// 1.先判断 number 的值
if (number > 0) {
// 从index位置开始删除number个数据
// 循环number次
for (let i = 0; i < number; i++) {
// 数据前移
for (let j = index; j < this.length - 1; j++) {
this[j] = this[j + 1];
}
// 每次都删最后一个(删除的同时变长度)
delete this[--this.length];
}
}
// 判断 data 是否存在
if (data) {
// data != undefined
// 数据后移
for (let i = this.length; i > index; i--) {
this[i] = this[i - 1];
}
this[index] = data; // 插入数据
this.length++;
}
},
// 12. 实现 forEach 函数
forEach: function(callback){
for(let i = 0; i < this.length; i++){
callback(this[i],i,this);
}
},
// 13. 实现 every 函数
every: function(callback){
let flag = true;
for(let i = 0; i < this.length; i++){
if(!callback(this[i],i,this)){
flag = false;
break;
}
return flag;
}
},
// 14. 实现 some 函数
some: function(callback){
let flag = false;
for(let i = 0; i < this.length; i++){
if(callback(this[i],i,this)){
flag = true;
break;
}
}
return flag;
},
// 15. 实现 filter 函数
filter: function(callback){
let newArr = [];
for(let i = 0; i < this.length; i++){
if(callback(this[i],i,this)){
newArr.push(this[i]);
}
}
return newArr;
}
};
// push
arr.push("张三");
arr.push("李四");
arr.push("刘涛");
arr.push("张子枫");
arr.push("章子怡");
arr.push("迪丽热巴");
arr.push("李一桐");
arr.push("关晓彤");
// arr.show();
console.log(arr);
console.log("------------");
// console.log(arr[0]);
// unshift
arr.unshift("赵丽颖");
console.log(arr);
console.log("--------------");
// pop
let last = arr.pop();
console.log(arr);
console.log("------------");
// shift
let first = arr.shift();
console.log(first);
console.log(arr);
console.log("-------------");
// sort
arr.sort((x, y) => {
x - y;
});
console.log(arr);
console.log("-------------");
// indexOf
// let index = arr.indexOf('王五'); // -1
let index = arr.indexOf("李四");
console.log(index);
console.log("------------");
// lastIndexOf
let index1 = arr.lastIndexOf("李四");
console.log(index1);
console.log("------------");
// splice
arr.splice(1, 2);
console.log(arr);
arr.splice(1, 0, "汪峰");
console.log(arr);
console.log("------------");
// join
let result = arr.join("");
console.log(result);
console.log("------------");
// slice
let result1 = arr.slice(-1, -2);
console.log(result1);