JavaScript的原型与继承

原型

  • 原型 prototype,我们所创建的每一个实例,解析器都会向这个函数中添加一个prototype,属性,这个属性会对应这个一个对象,这个对象就是原型对象(显式原型),原型对象就相当于一个公共的区域,当前实例都可以访问到这个原型对象

示例:

js 复制代码
Person.prototype.sayName = function () {
    console.log(this.name)
}
Person.prototype.xxx ='这是一个属性'
let p1 = new Person('张三',20,'男');
let p2 = new Person('李四',20,'男');
console.log(p1)
console.log(p2)
  • 如果函数作为普通的函数调用,那么prototype没有任何作用,当前函数以构造函数的方式调用时,它所创建的对象会隐含一个属性,指向该构造函数的原型对象
  • 我们可以通过proto(隐式原型),来访问到该属性
  • 当我们访问一个对象的属性或者方法时,会先在自身寻找(比如访问p1 对象的name属性)如果找不到则去原型对象中寻找,找到了直接使用
js 复制代码
console.log(p2.xxx);
//hasOwnProperty 判断这个属性是否是 p2特有的
console.log(p2.hasOwnProperty('xxx'))
//__proto__.hasOwnProperty('xxx') 判断这个属性是否共有的
console.log(p2.__proto__.hasOwnProperty('xxx'))

继承

原型链继承

js 复制代码
//定义父类构造函数
function SupperType(){
    this.subProp = '这是父类的一条消息';
    this.fuxxx = '这是父类的一条消息-测试';
}
//给父类的原型添加方法
SupperType.prototype.showSupperProp = function (){
    console.log("SupperType:",this.subProp,this.fuxxx)
}
//定义子类的构造函数
function  SubType(){
    this.subProp = '这是子类的一条消息';
}
//将子类的原型 指向父类实例
SubType.prototype = new SupperType();

//在子类的原型上添加方法
SubType.prototype.showSubProp = function (){
    console.log("SubType: ",this.subProp);
}

//将设置子类的原型构造函数为子类本身
SubType.prototype.constructor = SubType;
//创建子类实例  完成继承
var subType = new SubType();
//调用子类的方法
subType.showSubProp();
//调用父类方法
subType.showSupperProp();

console.log(subType.toString());
console.log(SubType.prototype.constructor)

原型链继承的特点:

  1. 原型链继承多个实例的引用类型属性指向相同一个实例被修改了原型属性,另一个实例的原型属性也会被影响
  2. 不能传递参数
  3. 继承单一

构造继承

js 复制代码
//创建父类构造
function SupperType(name){
    this.name = name;
    this.showSupperName = function (){
        console.log("SupperType: ",this.name)
    }
}

//创建子类构造
function SubType(name,age){
    //在子类中 继承父类 调用call方法 继承所有的属性与方法
    SupperType.call(this,name);
    this.age = age;
}

//给子类原型  定义方法
SubType.prototype.showSubName = function (){
    console.log("SubType: ",this.name,this.age)
}

let zzh = new SubType('渣渣辉',65);
zzh.showSupperName();
zzh.showSubName();
console.log(zzh);

构造继承的特点:

  1. 只能继承父类实例的属性和方法,不能继承原型属性和方法
  2. 无法实现构造函数的复用,每个子类都有父类的实例的函数副本
  3. 比较臃肿 ,影响性能

组合继承

组合继承就是将原型链继承和构造继承结合在一起

js 复制代码
function Person(name,age){
    this.name = name;
    this.age = age;
}
Person.prototype.setName = function (name) {
    this.name = name;
}
function Student(name,age,sex) {
    //------------构造继承-----
    Person.call(this,name,age);
    this.sex = sex;
}
// 原型链继承
Student.prototype = new Person();

Student.prototype.constructor = Student;

Student.prototype.setSex = function (sex) {
    this.sex = sex;
}

let s = new Student('李四',25,'男');
console.log(s.name,s.age,s.sex);
s.setName('王五');
s.setSex("女");
console.log(s.name,s.age,s.sex);
console.log(s);

特点:

  1. 父类中的实例属性和方法,在子类的实例中存在
  2. 也在子类的原型中存在,栈内存

数组

创建数组:

js 复制代码
var arr = new Array();
console.log(typeof arr);  //object
arr[0] = 'A';
arr[1] = 12;
arr[2] = true;
arr[3] = {name:'zs',sex:'男'}

使用字面量创建数组

js 复制代码
var arr =[1,'2',3,'4',5,6,'7',8,'9'];

通过length属性 获取数组长度

遍历数组

js 复制代码
for(let i = 0; i< arr.length; i++){
    console.log(arr[i])
}

向数组的末尾追加值

js 复制代码
arr.push("唐僧");
console.log(arr);

删除末尾数据

js 复制代码
arr.pop();
console.log(arr);

向数组的开头追加一个元素或者多个元素

js 复制代码
arr.unshift("牛魔王","铁扇公主");
console.log(arr);

删除数组的第一个元素

js 复制代码
arr.shift();
console.log(arr);

For Each遍历数组 IE 8 以上

第一个参数 :当前正在遍历的元素

第二个参数 :当前正在遍历的元素索引

第三个参数:当前正在遍历的数组

js 复制代码
arr.forEach(function (value,index,arr) {
    console.log(value,index,arr);
})

slice 截取指定元素,不会改变原数组参数

  • 1.截取的开始位置索引 包含开始索引元素
  • 2.截取的结束位置索引,不包含结束索引元素
  • 可以为负数 -1 表示倒数第一个元素 -2表示倒数第二个元素
js 复制代码
let newArr = arr.slice(0,3);
let newArr = arr.slice(0,-2);
console.log("原数组:",arr);
console.log("新数组:",newArr);

splice() 可以用于删除数组中的指定元素,该方法会影响到原数组,删除的元素会作为返回值返回参数

  • 1.表示开始位置索引
  • 2.要删除的元素数量
  • 3.第三个及后续参数参数,可以作为新的元素,插入到原数组中(开始索引的前面)
js 复制代码
var result = arr.splice(1,0,'朱大姐','沙和尚')
console.log("原数组:",arr);
console.log("新数组:",newArr);

concat 可以将两个或者多个数组 连接并返回一个新的数组 不会对原数组产生影响

js 复制代码
let arr1 = ['测试数据A', '测试数据B', '测试数据C'];
let arr2 = ['测试数据1', '测试数据2', '测试数据3'];
let arr3 = ['测试数据#', '测试数据$', '测试数据%'];

let result = arr1.concat(arr2, arr3, '连接后拼接A', '连接后拼接B');
console.log("拼接后:", result);
console.log(arr1,arr2,arr3)

let arr1 = ['测试数据A', '测试数据B', '测试数据C'];
数组拼接为字符串
console.log(arr1.join("#-#"));
数组反转
console.log(arr1.reverse());

数组元素排序:

js 复制代码
var arr = [1,2,5,8,6,5,7,8,9,3]
/**
 *  如果返回大于0 则元素交换位置
 *  如果返回小于0 则元素位置不变
 *  如果等于0则认为两个元素相同
 */
arr.sort(function (a,b){
    return b-a;
});
console.log(arr);
相关推荐
禁默5 分钟前
深入浅出:AWT的基本组件及其应用
java·开发语言·界面编程
Code哈哈笑15 分钟前
【Java 学习】深度剖析Java多态:从向上转型到向下转型,解锁动态绑定的奥秘,让代码更优雅灵活
java·开发语言·学习
joan_8518 分钟前
layui表格templet图片渲染--模板字符串和字符串拼接
前端·javascript·layui
程序猿进阶18 分钟前
深入解析 Spring WebFlux:原理与应用
java·开发语言·后端·spring·面试·架构·springboot
qq_4336184420 分钟前
shell 编程(二)
开发语言·bash·shell
charlie11451419135 分钟前
C++ STL CookBook
开发语言·c++·stl·c++20
袁袁袁袁满35 分钟前
100天精通Python(爬虫篇)——第113天:‌爬虫基础模块之urllib详细教程大全
开发语言·爬虫·python·网络爬虫·爬虫实战·urllib·urllib模块教程
还是大剑师兰特41 分钟前
什么是尾调用,使用尾调用有什么好处?
javascript·大剑师·尾调用
ELI_He99941 分钟前
PHP中替换某个包或某个类
开发语言·php
m0_748236111 小时前
Calcite Web 项目常见问题解决方案
开发语言·前端·rust