一面向对象
1面向对象介绍
1.1面向对象:是一种解决问题 思维方式
面向过程:注重的是过程
面向对象:注重的是结果
1.2面向对象 本质 是对面向过程的封装
2面向对象的编程举例
2.1给页面每一个div标签 和 p标签 设置颜色 和边框
//2.1获取元素
let divList = document.querySelectorAll("div")
let pList = document.querySelectorAll("p")
//2.2对象封装
let obj = {
setColor: function (arr, color) {
for (let i = 0; i < arr.length; i++) {
arr[i].style.backgroundColor = color
}
},
setBorder: function (arr, border) {
for (let i = 0; i < arr.length; i++) {
arr[i].style.border = border
}
}
}
//设置颜色
obj.setColor(divList,'red')
obj.setBorder(divList, '5px solid blue')
//第二种方式
$('div,p').css({
backgroundColor:'red',
border:'5px solid cyan'
})
内置对象
`` /* 内置对象: js作者提前封装好的对象 */
声明数a组
let arr = [10,20,30,40,50]// new Array(10,20,30,40,50)
//(1) arr.concat(数组) : 把两个数组连接成一个数组
//应用场景: 一般用于长列表(下一页),不断往后面拼接数组
let newArr = arr.concat([60,70,80,90])
console.log(newArr)
//(2) arr.reverse() : 翻转数组
//应用场景: 价格从低到高 切换成 从高到低, 只需要翻转数组即可
arr.reverse()
console.log( arr )
//(3) arr.join('分隔符') : 把数组每一个元素拼接成字符串
let arr1 = [80,90,55,60]
//应用场景 : 有些歌曲是多个人合唱,服务器会给我们一个数组。 这个时候就需要将数组元素通过join拼接起来然后再页面显示
let str = arr1.join('&')
console.log( str )//80&90&55&60
//(4) 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)
##字符串对象
1. 字符串类似于数组,也有长度和下标
// console.log( str.length )//16
// console.log( str[5] )//武
2.str.indexOf('字符串') 获取 ‘字符串’
果字符串不存在则返回固定值 -1
// // 应用场景: 一般用户判断 str中是否有某个字符串 如果没有则返回-1,
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']
4. str.substr(起始下标,截取长度)
一般后台返回的数据 不会和前端完全匹配。 有时候需要自己截取一部分
console.log( str.substr(2,5) )//从2下标开始,往后截取5个字
5.大小写转换 (中文没有大小写)
/应用场景: 字母验证码不区分大小写 (一般无论你输入什么,都会转成大写或小写保持格式统一)
console.log('dsSFJSGDJHsdfs'.toLocaleLowerCase() )//小写 dssfjsgdjhsdf
console.log('dsSFJSGDJHsdfs'.toLocaleUpperCase() )//大写 DSSFJSGDJHSDFS
工厂函数
3.1需求创建很多个对象(姓名,年龄,性别) 工厂函数:用于创建对象函数
//创建一个对象
let p={}
//给对象赋值
p.name=nmae
p.age=age
p.sex=sex
//返回这个对象
return p
}
//实列对象
let p1=CreatePerson('张三',20,'男')
let p2=CreatePerson('李四',20,'男')
console.log(p1,p2)
构造函数
1工厂函数 用于创建对象的函数 2构造函数“使用new调用函数 构造函数作用与工厂函数一直,都是来创建对象的,但是代码更加简洁
3构造函new工作原理 (1)创建空对象 (2)this指向这个对象 (3)对象赋值 (4)返回这个对象 4构造函数new在使用需要注意的地方 4.1构造函数首字一般是大写,为了提醒调用者不要忘记new关键字 4.2如果在构造函数内部,手动return return 值类型:无效,还是返回new创建对象 return 引用类型:有效 会覆盖new创建的对象
// 创建对象 {}
// this 指向这个对象
// 对象赋值
this.name=name
this.age=age
this.sex=sex
// return [20,30,50]
// 返回这个对象
}
let p1= new Person('张三',20,"男")
console.log(p1)
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)
/* 3.使用对象 : 解决内存浪费 + 变量污染 */
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)
原型对象
原型是属性
1原型对象是什么?任何函数在声明的时候,系统会自动帮你创建一个对象,称之为原型对象 2原型对象的作用?解决 内存浪费 +变量污染 3.原型对象相关三个属性 : 描述 构造函数、原型对象、实例对象三者关系
prototype : 属于构造函数, 指向原型对象
__proto__ : 属于实例对象,指向原型对象
constructor : 属于原型对象,指向构造函数
prototype : 属于构造函数, 指向原型对象
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
__proto__ : 属于实例对象,指向原型对象
//1.构造函数
function Person(name,age){
this.name = name
this.age = age
}
//2.原型对象
Person.prototype.eat = function(){
console.log('吃东西')
}
Person.prototype.learn = function(){
console.log('学习')
}
//3.实例对象
let p1 = new Person('张三',20)
console.log(p1)
/* 为什么实列对象可以直接访问原型中的成员 本质是通过_ proto_来访问的
__proto__ : 属于实例对象的,指向原型对象
注意: 这个属性不是web标准,很多浏览器不会显示的。 这个属性在开发中不能使用,只能用于学习研究
*/
console.log(p1._proto_)
p1.eat()//p1.__proto__.eat()
// console.log(p1._proto_===Person.prototype)
``` //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
constructor : 属于原型对象,指向构造函数
let p1 = new Person('张三',20)
console.log(p1)
let p2=new Person('李四',20)
console.log(p2)
/* __proto__ : 属于实例对象的,指向原型对象
注意: 这个属性不是web标准,很多浏览器不会显示的。 这个属性在开发中不能使用,只能用于学习研究
*/
p1.eat()//p1.__proto__.eat()
p2.learn()
/* 验证 构造函数、原型对象、实例对象三者关系 */
console.log( p1.__proto__.constructor )//Person
console.log( Person.prototype === p1.__proto__ )//true
静态成员
静态成员: 函数的属性
实例成员: 实例对象的属性
*/
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 ) //静态成员
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)
// object静态方法 Object.values(对象名)
console.log(Object.keys(obj))
console.log(Object.values(obj))