01-面向对象
1.面向对象是注重结果的思维方式
面向过程: 注重过程.
举例:吃火锅-买食材-买锅电磁炉-煮熟开吃
弊端:(1)代码冗余:相同代码重复使用 (2)维护不便
面向对象: 注重结果
举例:点外卖
2.面向对象与面向过程的关系
面向对象本质: 面向过程的封装
封装: 把代码放入对象的方法中
直接放入函数中: 功能过多就会导致全局变量污染
02-面向对象编程案例
02-内置对象api
学习传送门:https://www.runoob.com/jsref/jsref-obj-array.html
内置对象: JS作者提前封装好的对象
-
- api : 预先定义的函数
- 学习内置对象: 不需要死记硬背,忘记了随时查阅文档。 用多了自然就记住了,熟能生巧
1.1-数组对象api
/*1.数组的增删改查操作
新增元素到最后面 : arr.push( 元素 )
新增元素到最前面 : arr.unshift()
删除最后一个元素 : arr.pop()
删除第一个元素 : arr.shift()
删除指定位置元素 : arr.splice(起始下标,删除数量)
*/
| join() | 把数组的所有元素放入一个字符串。 |
|---|
| reverse() | 反转数组的元素顺序。 |
|---|
| sort() | 对数组的元素进行排序。 |
|---|
2.将数组中的每一个元素都拼接成一个字符串
let str = arr .join( )//10,20,30
3.翻转数组
var newArr = arr.reverse()
4.arr2.sort(function (a, b) {
return b - a//从大到小
})
console.log(arr2)
//声明数组
let arr = [10, 20, 30, 40, 50]
// 1. arr.concat(数组) :把两个数组链接成一个数组
//应用场景:一般用于长列表(下一页),不断往后面拼接数组
let newArr = arr.concat([60, 70, 80, 90])
console.log(newArr)
arr.reverse()
//应用场景:价格从低到高切换成从高到低, 只需要翻转数组即可
console.log(arr)
let arr1 = [80, 90, 55, 60]
let str = arr1.join('|')
//应用场景:有些歌曲多人合唱,服务器会给我们一个数组,这个时候就需要用join拼接起来在页面显示
console.log(str)//80|90|55|60
let arr2 = [80, 90, 50, 40, 20, 70]
arr2.sort(function (a, b) {
return b - a//从大到小
})
console.log(arr2)
(1)arr.concat(数组) : 把两个数组连接成一个数组.
//应用场景: 一般用于长列表(下一页),不断往后面拼接函数
let newArr =arr.concat([60,70,80,90)]
(2)arr.reverse() ;翻转数组
应用场景
1.2-字符串对象api
| indexOf() | 搜索数组中的元素,并返回它所在的位置。 |
|---|---|
| toLowerCase | 转为小写 |
| toUpperCase | 转为大写 |
| let arry = str3.split("&") | //以&符号分隔字符串 [我,爱,你] |
| str2 = str.replace | 第一个参数:要修改的字符串 第二个参数:修改后的字符串 |
let str = "江城武汉是英雄的城市!";
//1 判断一个字符串在不在某个字符串里面
let index1 = str.indexOf("武汉")//如果存在,则返回参数字符串首字母所在的下标
let index2 = str.indexOf("城")
let index3 = str.indexOf("武城")//如果不存在,则返回 -1
console.log ( index1, index2, index3 )//0,6,-1
//2 截取字符串 第一个参数:从哪个下标开始截取 第二个参数:截取的长度
let str1 = str.substr(2,5)//武汉是英雄
console.log ( str1 )
//3 修改字符串 第一个参数:要修改的字符串 第二个参数:修改后的字符串
let str2 = str.replace("江城","大江大河大")
console.log ( str2 )//大江大河大武汉是英雄的城市!
//4 分隔字符串:将字符串按照指定的符号分隔,得到一个数组
let str3 = "我&爱&你"
//这个函数的返回值一定是一个数组
let arry = str3.split("&")//以&符号分隔字符串 [我,爱,你]
console.log ( arry )// [我,爱,你]
//5 大小写转换 (只有英文才有大小写,中文不存在大小写)
console.log ( "AKlkshflsLKJHDHL".toLowerCase () )//转为小写 aklkshflslkjhdhl
console.log ( "AKlkshflsLKJHDHL".toUpperCase () )//转为大写 AKLKSHFLSLKJHDHL
console.log ( "中文不存在大小写".toLowerCase () )//转为小写
03-原型对象
1.1.1-了解工厂函数
工厂函数:用于批量创建对象的函数
//1.需求:创建3个人对象 (姓名name,年龄age,性别sex)
//弊端:(1)代码冗余 (2)维护不便
// let person1 = {
// name:'ikun',
// age:32,
// sex:'男'
// }
// let person2 = {
// name:'班长',
// age:38,
// sex:'男'
// }
// let person3 = {
// name:'王悦',
// age:28,
// sex:'男'
// }
//2.使用函数创建对象 : 解决创建多个对象代码冗余
//工厂函数 :
function createPerson (name, age, sex) {
//(1)创建空对象
let p = {}
//(2)对象赋值
p.name = name
p.age = age
p.sex = sex
//(3)返回创建好的对象
return p
}
let p1 = createPerson('ikun', 32, '男')
let p2 = createPerson('班长', 38, '男')
let p3 = createPerson('王悦', 28, '男')
console.log(p1, p2, p3)
1.1.2-重点构造函数==
1.工厂函数(了解) : 用于创建对象的函数
2.构造函数 : 使用new调用一个函数
构造函数作用与工厂函数一致,都是用来创建对象的。但是代码更加简洁。
3.构造函数new工作原理
(1)创建空对象
(2)this指向这个对象
(3)对象赋值
(4)返回这个对象
4.构造函数new在使用时需要注意的地方
4.1 构造函数首字母一般大写, 为了提醒调用者不要忘记new关键字
4.2 如果在构造函数内部 手动return
return 值类型 : 无效,还是返回new创建的对象
return 引用类型 : 有效,会覆盖new创建的对象
function Person(name,age,sex){
//(1)创建空对象 {}
//(2)this指向这个对象 this = {}
//(3)对象赋值
this.name = name
this.age = age
this.sex = sex
//(4)返回这个对象 return this
}
let p1 = new Person('张三',20,'男')
console.log(p1)
原型对象01(构造函数资源浪费)
1.原型对象是什么? : 任何函数在声明的时候,系统会自动帮你创建一个对象,称之为原型对象
2.原型对象作用? : 解决 内存浪费 + 变量污染
3.原型对象相关三个属性 : 描述 构造函数、原型对象、实例对象三者关系
prototype : 属于构造函数, 指向原型对象
proto : 属于实例对象,指向原型对象
- 原型:任何构造函数在被创建的时候,系统都会自动帮我们创建一个与之对应的对象.
-
- 同时解决内存浪费与全局变量污染的问题
- 谁可以访问原型对象中的成员(属性和方法)
-
- 构造函数自身:
构造函数名.prototype - 构造函数实例化的每一个对象:点语法直接访问
- 构造函数自身:
let obj = {
eat: function() {
console.log("吃东西")
},
learn: function() {
console.log("学习")
}
}
function Person(name, age) {
this.name = name
this.age = age
this.eat = obj.eat
this.learn = obj.learn
}
let p1 = new Person("张三", 18)
let p2 = new Person("李四", 20)
console.log(p1, p2)
原型对象02(原型对象)
//构造函数
function Person(name, age) {
this.name = name
this.age = age
}
//原型对象
console.log(Person.prototype)
Person.prototype = {
eat: function() {
console.log("吃东西")
},
learn: function() {
console.log("学习")
}
}
//实例对象 : 用new调用构造函数,返回的那个对象(new创建的那个对象)
let p1 = new Person('张三',20)
console.log( p1 )
let p2 = new Person('李四',22)
console.log( p1.eat == p2.eat )//true
1.3- __proto__属性介绍
-
1.属于对象,指向实例化这个对象的构造函数对应的原型
-
2.proto属性不是W3C的标准属性,所以实际开发中一般不会使用它来访问原型
-
往原型添加属性方法,最好使用构造函数来访问
构造函数名.prototype
1.prototype属性: 属于构造函数,指向原型对象
* 作用: 解决构造函数资源浪费+变量污染
2.__proto__属性: 属于实例对象,指向原型对象
* 作用: 可以让实例对象访问原型中的成员
*/
//1.构造函数
function Person (name, age) {
this.name = name
this.age = age
}
//2.原型对象
Person.prototype.eat = function () {
console.log('我中午真的吃了红烧武昌鱼')
}
Person.prototype.country = '中国人'
//3.实例对象
let p1 = new Person('班长', 28)
console.log(p1)
/*
__proto__ : 属于实例对象,指向原型对象
*/
console.log( Person.prototype === p1.__proto__ )//true
//实例对象为什么可以直接访问原型中的成员,其实都是通过__proto__来访问的
/*
1.虽然实例对象可以直接访问原型的原理是 __proto__,但是开发中不推荐使用
2.原因: __proto__不是ECMA标准语法,有一些浏览器不支持。
3.结论: 学习阶段,学习原型可以用__proto__. 实际开发中,建议省略__proto__
*/
p1.eat()//p1.__proto__.eat()
1.4-constructor属性介绍
3.constructor: 属于原型对象,指向构造函数
* 作用: 可以让实例对象 知道自己被哪一个构造函数创建的
*/
//1.构造函数
function Person (name, age) {
this.name = name
this.age = age
}
//2.原型对象
Person.prototype.type = '哺乳动物'
Person.prototype.eat = function () {
console.log('吃东西')
}
//3.实例对象
let p1 = new Person('布丁', 3)
p1.eat()
console.log(p1.type)
/*
constructor : 属于原型对象,指向构造函数
作用:可以让实例对象知道自己被那个构造函数创建的
*/
console.log(Person.prototype.constructor)//Person
console.log(Person.prototype.constructor === Person )//true
console.log( p1.constructor )//Person p1.__proto__.constructor
1.5-静态成员与实例成员
构造函数也可以有自己的属性: 例如prototype
静态成员 : 属于函数对象的成员
实例成员: 属于实例化对象的成员
*/
//构造函数
function Person(name,age){
this.name = name;
this.age = age;
};
Person.aaa = '啊啊啊';
console.log(Person.aaa);//静态成员
//实例化对象
let p1 = new Person('张三',20);
console.log(p1.name);//实例成员
console.log(p1.age);//实例成员