1.面向对象是什么
面向对象是什么: 面向对象是一种注重结果的思维方式 面向过程: 注重过程 面向对象: 注重结果
2.面向对象与面向过程的关系 :面向对象的本质 就是 对面向过程的 封装
举例:吃火锅
1.面向过程:注重过程
(1)买鸳鸯锅
(2)买电磁炉
(3)买锅底
(4)买牛肉、羊肉、青菜、千张、毛肚、火锅面、菌类
(5)开火热锅
(6)放食材
(7)夹起来开干
2.面向对象:注重结果
点火锅送过来
3.内置对象
内置对象: js作者提前封装好的对象
3.1数组对象
声明数组
let arr = [10,20,30,40,50]// new Array(10,20,30,40,50)
3.1.1 arr.concat(数组):连接对象
// 应用场景:下拉加载更多的时候,会把新数组链接到原来数组的后面
arr = arr.concat([40,50,60])//链接两个或更多的数组,得到一个拼接后的新数组,需要接收
console.log(arr);
3.1.2 arr.reverse(数组):翻转对象
//应用场景: 价格从低到高 切换成 从高到低, 只需要翻转数组即可
arr.reverse()
console.log( arr )
3.1.3 arr.join(‘分隔符’):把数组的每一个元素拼接成字符串
let arr1 = [80,90,55,60]
//应用场景 : 有些歌曲是多个人合唱,服务器会给我们一个数组。 这个时候就 需要将数组元素通过join拼接起来然后再页面显示
let str = arr1.join('&')
console.log( str )//80&90&55&60
3.1.3 arr.sort(function(a,b){return a-b}):排序
let arr2 = [80,90,50,20,77,88]
arr2.sort( function(a,b){
// return a-b //从小到大
return b-a //从大到小
} )
console.log(arr2)
3.2字符串对象
声明一个字符串
let str = '黑马程序员武汉大前端女神节快乐!'
3.2.1 字符串类似于数组,也有长度和下标
console.log( str.length )//16
console.log( str[5] )//武
3.2.2 str.indexOf('字符串') 获取字符串在str中的首字母下标
如果字符串存在则返回首字母下标,如果字符串不存在则返回固定值-1
// 应用场景: 一般用户判断 str中是否有某个字符串 如果没有则返回-1,不是-1说明有
let index1 = str.indexOf('大前端')
console.log( index1 )//7
let index2 = str.indexOf('大女神')
console.log( index2 )//-1
3.2.3 str.split('分隔符') 用分隔符切割字符串,得到切割之后的数组
// 应用场景 : 一般用户解析 网址
let url = 'http://www.baidu.com?name=张三&age=20'
console.log( url.split('|') )//['http://www.baidu.com?name=张三&age=20']
console.log( url.split('?') )//['http://www.baidu.com', 'name=张三&age=20']
console.log( url.split('=') )//['http://www.baidu.com?name', '张三&age', '20']
3.2.4 str.substr(起始下标,截取长度) 截取字符串
// 应用场景 : 一般后台返回的数据 不会和前端完全匹配。 有时候需要自己截取一部分
//例如: 商品价格后台返回 :价格58元 但是前端只需要显示58元,就需要截取
console.log( str.substr(2,5) )//从2下标开始,往后截取5个字 程序员武汉
3.2.5 大小写转换 (中文没有大小写)
//应用场景: 字母验证码不区分大小写 (一般无论你输入什么,都会转成大写或小写保持格式统一)
console.log('dsSFJSGDJHsdfs'.toLocaleLowerCase() )//小写 dssfjsgdjhsdfs
console.log('dsSFJSGDJHsdfs'.toLocaleUpperCase() )//大写 DSSFJSGDJHSDFS
4.工厂函数
<script>
/* 需求 : 需要创建很多个对象 (姓名、年龄、性别) */
// let p1 = {
// name:'张三',
// age:20,
// sex:'男'
// }
// let p2 = {
// name:'李四',
// age:22,
// sex:'女'
// }
// let p3 = {
// name:'王五',
// age:30,
// sex:'男'
// }
// 工厂函数 : 用于创建对象的函数
function createPerson(name,age,sex){
//1.创建对象
let p = {}
//2.给对象赋值
p.name = name
p.age = age
p.sex = sex
//3. 返回对象
return p
}
let p1 = createPerson('张三',20,'男')
let p2 = createPerson('李四',22,'女')
console.log(p1,p2)
</script>
5.构造函数
1.工厂函数:用于创建对象的函数
2.构造函数:使用new调用一个函数 构造函数作用与工厂函数一致,都是用来创建对象的。但是代码更加简洁
3.构造函数new工作原理 (1)创建空对象 (2)this 指向这个对象 (3)对象赋值 (4)返回这个对象
4.构造函数new在使用时需要注意的地方 4.1构造函数首字母一般大写,为了提醒调用者不要忘记new关键字 4.2如果在构造函数内部 手动return return 值类型 :无效,还是返回new创建的对象 return 引用类型:有效,会覆盖new创建的对象
<script>
/*
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)
// JS中几乎所有的对象都是构造函数创建
/*
数组: new Array()
对象: new Object()
日期:new Date()
正则: new RegExp()
*/
</script>
6.原型对象
6.1原型对象是什么?
任何函数在声明的时候,系统会自动帮你创建一个对象,称之为原型对象
6.2原型对象的作用
(1)构造函数内部方法: 浪费内存资源
function Person(name,age){
this.name = name
this.age = age
this.eat = function(){
console.log('eat');
}
}
let p1 = new Person('张三',18)
let p2 = new Person('李四',20)
console.log( p1,p2)
思考: p1和p2都有eat方法,而是函数体相同。但是他们是同一个函数吗?
不是同一个: 因为每一次调用构造函数, 内部都会执行一次function,就会在堆中开辟一个新的空间。虽然代码是一样的,但是地址不同。 就会导致每调用一次构造函数,多出一个函数堆空间。导致内存资源浪费
引用类型只比较地址,不比较值。 不能因为值相同,就认为引用类型地址相同
console.log( p1.eat == p2.eat )//false
(2)使用全局函数解决内存浪费 导致新的问题: 全局变量污染
let eat = function() {
console.log("吃东西")
}
let learn = function() {
console.log("学习")
}
function Person(name, age) {
this.name = name
this.age = age
this.eat = eat
this.learn = learn
}
let p1 = new Person("张三", 18)
let p2 = new Person("李四", 20)
console.log(p1, p2)
思考题:p1的eat和p2是不是同一个 答案:是的 因为构造函数内部并没有重新function创建一个函数,而是拷贝eat的地址赋值。 无论你调用构造函数多少次,都是拷贝eat的地址
console.log( p1.eat == p2.eat )//true
(3)使用对象 : 解决内存浪费 + 变量污染
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)
6.3原型对象相关三个属性:构造函数 、原型对象、实例对象 三者关系
prototype : 属于构造函数, 指向原型对象
解决构造函数内存浪费+变量污染
__proto__ : 属于实例对象,指向原型对象
让实例对象直接使用原型的成员(函数+属性)
constructor : 属于原型对象,指向构造函数
让实例对象知道自己的构造函数是谁
//1.构造函数
function Person(name,age){
this.name = name
this.age = age
}
//2.原型对象
Person.prototype.eat = function(){
console.log('吃东西')
}
Person.prototype.learn = function(){
console.log('学习')
}
console.log( Person.prototype.constructor )//Person
// 可以让实例对象知道自己被哪一个构造函数创建
//3.实例对象
let p1 = new Person('张三',20)
console.log(p1)
/* __proto__ : 属于实例对象的,指向原型对象
注意: 这个属性不是web标准,很多浏览器不会显示的。 这个属性在开发中不能使用,只能用于学习研究
*/
p1.eat()//p1.__proto__.eat()
/* 验证 构造函数、原型对象、实例对象三者关系 */
// console.log(p1.__proto__);//p1的原型对象
console.log( p1.__proto__.constructor )//Person
console.log( Person.prototype === p1.__proto__ )//true
7.静态成员与实例成员
静态成员: 函数的属性
实例成员: 实例对象的属性
/*
静态成员: 函数的属性
实例成员: 实例对象的属性
*/
function Person(name,age){
this.name = name
this.age = age
}
let p1 = new Person('张三',20)
console.log( p1.name )//实例成员
console.log( p1.age )//实例成员
console.log( Person.prototype )//静态成员
console.log( Math.PI ) //静态成员
</script>
8.Object的values方法
/* 需求:获取对象所有的属性值 */
let person = {
name:'张三',
age:20,
sex:'男'
}
//1 以前的写法: for-in 循环
for(let key in person ){
console.log( person[key] )
}
//2.静态方法 Object.values(对象名)
//返回值是一个数组,会存储对象每一个属性值
let arr = Object.values(person)
console.log(arr)
</script>