面向对象
是一种编程思想,实现了这种思想的编程语言,我们也可以称为面向对象
三大特征:
封装性:隐藏内部细节,只对外开发操作接口(对象的方法)
继承性:一个对象可以继承另一个对象的成员,在不改变另一个对象的前提下进行扩展。
多态性:同一个操作作用于不同的对象会产生不同的结果。(js中的变量存储)
对象:
定义:
通过{ }来实现的,对象的成员是一个键值对,多个成员之间由,(逗号)隔开。
空对象:
var o1 = {
}
单个成员的对象
var o2 = {
name:"jack"
}
多个成员的对象
var o3= {
name:"jack",
age:18,
sex:'男'
......
}
含成员和方法的对象
var o4 ={
name:'angle',
age:25,
gender:'女',
say:function(){
console.log('hello')
}
}
访问对象的成员,对象名,成员名。
对象成员的遍历
for … in来完成
for(obj in o4)
重点:对象的拷贝(复制)
浅拷贝:
将原对象的快捷方式拷贝给了拷贝对象(对象本身没有进行复制),两个对象指向同样的内存空间
**优点:**可以节省内存空间
深拷贝:
真正的创建了一个对象的副本,把这个副本复制给另一个对象
// 深拷贝
function deepCopy(obj){
var p2 = {
}
for(var k in obj){
//遍历obj的成员,判断obj[k]的类型,用到了递归
p2[k] = (typeof obj[k] === 'object')?deepCopy(obj[k]):obj[k]
}
return p2
}
var p3 = {
name:'jack',
age:18,
subject:{
name:['html','css','javascript']
}
}
var p4 = deepCopy(p3)
console.log(p3 === p4)
p4.name = '猪猪'
console.log(p3)
console.log(p4)
构造函数
是javascript创建对象的另外一种方式,和{}不同的是:它可以创建若干具有相同特征的对象。
function factory(age,name){
var obj = {
}
obj.name = name;
obj.age = age;
return obj;
}
var o1 = factory('曹操',24)
var o2 = factory('刘备',30)
console.log(o1)
console.log(o2)
javascript内置构造函数
new 构造函数名([形参1,形参2])
Object:new Object()
String:new String('123456')
Date:new Date('2021-03-12')
......
访问对象的构造函数:
通过对象的constructor
对象名.constructor
私有成员
在构造函数中,用var定义的变量,我们把它称之为私有成员,私有成员不能通过对象名.成员名
的方式访问
var name = ‘javaScript’
若要访问私有成员必须在构造函数中嵌套定义一个函数,用来返回私有成员的值
function Person(){
var name = 'javaScript'
//必须加this
this.getName = function(){
return name
}
}
var o1 = new Person();
console.log(o1.getName())
This关键字
主要在函数中使用,根据函数调用的环境不同,this的指向也会不同。
1.使用new 关键字将某个函数作为构造函数调用时:
构造函数内部的This指向新创建的对象
此时的this指向O1
2.直接通过函数名调用函数时,函数中的This指全局对象
浏览器中的this指向window对象
3.如果将函数作为方法调用,this指向该对象。
改变This的指向
apply()
call()
function method(){
console.log(this.name)
}
method.apply({
name:'张三'})
method.call({
name:'李四'})
第一个this指向张三,第二个this指向李四
常用的内置对象
String:字符串对象
Number:数值对象
Math:数学运算对象
Date:日期时间对象
Array:数组对象
原型和继承
每创建一个函数,就会随之有一个对象存在,函数通过prototype属性指向该对象。
原型:又称为原型对象,指的是方法所对应的对象
如何通过原型来实现继承?
1.传统的继承,一个对象没有某个属性或方法,但是可以从另一个对中获取
function Person(name){
this.name = name
}
Person.prototype.sayHello = function(){
console.log('Hello'+this.name)
}
var p1 = new Person('关羽')
p1.sayHello()
2.替换原型对象实现继承,将构造函数的原型对象替换成一个新的对象,那么基于该构造函数创建的对象就会继承新的原型对象。
function Person(){
}
Person.prototype = {
sayHello:function(){
console.log('你好,我是新对象')
}
}
var p = new Person()
p.sayHello()
3.利用object.create()实现继承
var obj = {
sayHello:function(){
console.log('我是一个带有sayHello方法的对象')
}
}
//相当于newObj继承了obj的功能
var newObj = Object.create(obj)
newObj.sayHello()
// __proto__是寻找它的原型对象
console.log(newObj.__proto__ === obj)
原型链
对象有原型对象,原型对象也有自己的原型对象,这样的链式结构称之为原型链。
函数的本质是对象,因此函数也有构造函数,所有内置对象的构造函数,都是function函数
console.log(String.constructor)
console.log(Number.constructor)
原型对象的原型对象:对象的原型通过对象.constructor.prototype
来获取,因为constructor这个属性又指向构造函数构成了循环,无法访问原型对象的原型。为了解决这个问题有些浏览器为对象增加了新的属性__proto__
来用来指向原型对象的原型(火狐,谷歌)
原型链的结构
自定义函数,以及Object,String,Number等等的内置函数,它都是由function函数来创建,function函数都是由function函数自身来创建的
每个构造函数都有一个原型对象,构造函数通过prototype属性指向原型对象,原型对象通过constructor属性指向构造函数。
由构造函数创建的实例对象,继承自构造函数的原型对象,通过实例对象的__proto__
属性,可以直接访问原型对象
构造函数的原型对象继承自Object的原型对象,而Object的原型对象的__proto__
属性为null
instanceof运算符,用来检测一个对象的原型链中,是否含有某个构造函数的prototype属性所表示的对象。
数组
类型相同的数据的集合
创建数组
使用array对象创建
var arr = new Array()
var arr = new Array(‘a1’,‘a2’,‘a3’)
使用[]来创建数组
var tmp = [1,2,3]
数组的基本操作
获取数组长度
Array对象提供length属性,存放数组的长度。
数组长度 = 数组下标 + 1
数组访问和遍历
访问数组元素
数组名[索引]
遍历
for … in…循环来完成
数组添加,删除,修改
添加:数组名.push(数据) 数组名.unshift(数据)
修改:数组名[索引] = 值
删除:delete 数组名[下标]
数组排序
冒泡排序:
// 冒泡排序 12 升序排列
var arr = [10,22,1,24,4,2,13,5,7,3,0,99]
console.log('待排序数组是'+arr)
for(var i=0;i<arr.length;i++){
for(var j=0;j<arr.length-i;j++){
if(arr[j]>arr[j+1]){
// var flag = arr[j+1];
// arr[j+1] = arr[j];
// arr[j] = flag
[arr[j],arr[j+1]] = [arr[j+1],arr[j]]
}
}
}
console.log("排序后的数组为"+arr)
插入排序:
从最后一个元素向前遍历
// 插入排序
var arr = [12,1,15,46,23,45,34,22,345]
console.log('需排序数组'+arr)
for (var i = 0;i<arr.length;i++){
for(var j = i;j>0;j--){
if(arr[j-1]>arr[j]){
[arr[j-1],arr[j]] = [arr[j],arr[j-1]]
}
}
}
console.log('排序后的为'+arr)
选择排序
for(var i=0;i<arr.length;i++){
var min = arr[i];
var k = i;
for(var j=i+1;j<arr.length;j++){
if(min > arr[j]){
min = arr[j];
k = j;
}
}
if(k !=i){
[arr[i],arr[k]] = [arr[k],arr[i]]
}
}
常用数组的操作方法
栈和队列的方法:
push()—给数组的尾部添加新元素,返回数组的新长度
unshift()—给数组的开头添加新元素,返回数组的新长度
pop()—从数组的末尾移出并返回一个元素,如果数组为null就返回undefined
shift()—从数组的开头移出并返回一个元素,如果数组为null就返回undefined
检索方法:
includes()—确定数组中,是否含有某个元素,有则返回true,无则返回false
indexof()—返回给定元素的第一个索引
lastIndexOf()—返回给定元素在数组中的最后一个索引值(下标)
Array.IsArray()—判断传递过来的值,是否是一个数组,返回:是–true,不是–false
数组转字符串:
join()—将数组中的所有元素连接到一个字符串中
toString()—将数组转化为字符串
其他:
sort()—对数组进行排序并返回数组(默认升序)
fill()—用一个固定值填充数组中指定下标范围内的所有元素
reverse()—颠倒数组中所有元素的位置
splice()—在指定范围内对数组添加或删除元素
cancat()—合并两个或两个以上的数组
slice()—在指定范围内的数组拷贝到一个新数组中去