zoukankan      html  css  js  c++  java
  • JavaScript面向对象基础

    初识对象

    • 面向对象的特征

      • 封装性、继承性、多态性
      • 对象是键值对的集合:对象是由属性和方法构成的 (ps:也有说法为:对象里面皆属性,认为方法也是一个属性)
    • 对象属性操作

        var student = {
            name: 'sunny',
            age: 20,
            number: '11034P',
            department: 'newEnergy',
            score: function(){
                return '成绩查询系统!';
            },
            job: function(){
                return '就业查询系统!';
            }
        }
        var arr = [];
    
        // .语法
        // .语法后面不能使用js中的关键字、保留字(class、this、function。。。)
        // .语法后面不能使用数字
        // .语法后面可直接执行方法函数
        console.log(student.name);
        console.log(student.score());
    
        // []语法
        // []内部必须用引号引入变量名 (student['number']
        // ["class"]、["this"]等保留字都可以随意使用
        // [0]、[1]、[2]也可以使用 ? 为什么obj[3]==obj["3"]
        // 甚至还可以这样用:["[object Array]"]  jquery里面就有这样的实现
        // 也可以这样用:["{abc}"]  给对象添加了{abc}属性
        console.log(student['age']);
        console.log(student['job']);
    
        // 添加属性
        student['[object Array]'] = 240;
        student['{object}'] = {'arts':85, 'sports': 95};
        for(key in student){
            arr.push(key);
        }
        console.log(student);
        console.log(arr);
        arr = [];
    
        // 修改属性
        student.gender = 'man';
        student['direction'] = function(){
            return '人工智能与图形操作';
        }
        for(key in student){
            arr.push(key);
        }
        console.log(student);
        console.log(arr);
        arr = [];
    
        // 删除属性
        delete student.number;
        for(key in student){
            arr.push(key);
        }
        console.log(student);
        console.log(arr);
        arr = [];
    
    • 获取对象长度的方法
      • 对象的长度不能用.length获取
      • Object具有一个keys属性,可以返回json对象的key的数组
      • Object可以使用in运算符
        var student = {
            name: 'sunny',
            age: 20,
            number: '11034P',
            department: 'newEnergy',
            score: function(){
                return '成绩查询系统!';
            },
            job: function(){
                return '就业查询系统!';
            }
        }
    
        var arr = [];
    
        arr = Object.keys(student);
        console.log(arr.length);
        arr = [];
    
        for(key in student){
            arr.push(key);
        }
        console.log(arr.length);
        arr = [];
    
        console.log('name' in student);
    
    • 对象的浅拷贝与深拷贝
        // 浅拷贝
        var student = {
            name: 'sunny',
            age: 20,
            number: '11034P',
            department: 'newEnergy',
            score(){
                return '成绩查询系统!';
            },
            job(){
                return '就业查询系统!';
            }
        }
        var simple = obj=>{
            let newObj = {};
            for(let key in obj){
                newObj[key] = obj[key];
            }
            return newObj;
        }
        var sunny = simple(student);
        console.log(sunny);
    
        // 深拷贝
        var student = {
            name: 'sunny',
            age: 20,
            number: '11034P',
            department: 'newEnergy',
            score: {
                arts: 95,
                sports: 85,
                program: 95
            },
            job(){
                return '就业查询系统!';
            }
        }
    
        var deepCopy = obj=>{
            var newObj = {};
            for(let key in obj){
                newObj[key] = (typeof obj[key] === 'object') ? deepCopy(obj[key]) : obj[key];
            }
            return newObj;
        }
        var sunny = deepCopy(student);
        console.log(sunny);
    

    构造函数

    • 构造函数的概念

      • 任何函数都可以当成构造函数
      • 只要把一个函数通过new的方式来进行调用,我们就把这一次函数的调用方式称之为:构造函数的调用
        • new CreateFunc(); 此时CreateFunc就是一个构造函数
        • CreateFunc(); 此时的CreateFunc并不是构造函数
      • new Object()等同于对象字面量{}
    • 构造函数的执行过程

      • var p1=new Person();
      • 创建一个对象 (我们把这个对象称之为Person构造函数的实例)- _p1
      • 创建一个内部对象,this,将this指向该实例(_p1)
      • 执行函数内部的代码,其中,操作this的部分就是操作了该实例(_p1)
      • 返回值:
        • 如果函数没有返回值(没有return语句),那么就会返回构造函数的实例(_p1)
        • 如果函数返回了一个基本数据类型的值,那么本次构造函数的返回值是该实例(_p1)
        • 如果函数返回了一个引用数据类型的值,那么本次函数的返回值就是该值
    • 创建构造函数

        var student = {};
        student.name = 'sunny';
    
    • 内置的构造函数
        var obj = new Object();
        var num = new Number();
        var str = new String();
        var now = new Date();
        var arr = new Array();
        var reg = new RegExp();
        var bool = new Boolean();
        var func = new Function();
        var img = new Image();
    
    
        console.log(obj);
        console.log(obj.constructor);
    
        console.log(num);
        console.log(num.constructor);
    
        console.log(str);
        console.log(str.constructor);
    
        console.log(now);
        console.log(now.constructor);
    
        console.log(arr);
        console.log(arr.constructor);
    
        console.log(reg);
        console.log(reg.constructor);
    
        console.log(bool);
        console.log(bool.constructor);
    
        console.log(func);
        console.log(func.constructor);
    
        console.log(img);
        console.log(img.constructor);
    
    • 自定义构造函数
      • 构造函数的命名推荐采用帕斯卡命名规则,即所有的单词首字母大写。
      • 在构造函数内部,使用this来表示刚刚创建的对象。
        var Computer = function(memory, storage, videoMemory, run){
            this.memory = memory;
            this.storage = storage;
            this.videoMemory = videoMemory;
            this.run = run;
            this.introduce = function(){
                return this.memory;
            }
        }
        var noteBook = {
            memory: '16GB',
            storage: '2TB',
            videoMemory: '4GB',
            run: function(){
                return '你好,世界!';
            }
        }
        var Dell = new Computer(noteBook.memory, noteBook.storage, noteBook.videoMemory, noteBook.run);
        console.log(Dell);
        console.log(Dell.run());
        console.log(Dell.introduce());
    
    • 私有成员
      • 在构造函数中,使用var关键字定义的变量称为私有成员
      • 在实例对象后无法通过“对象成员”的方式进行访问
      • 但是私有成员可以在对象的成员方法中访问
        var Computer = function(memory, storage, videoMemory, run){
            var processor = 'Core i7-4700MQ';
            this.memory = memory;
            this.storage = storage;
            this.videoMemory = videoMemory;
            this.run = run;
            this.introduce = function(){
                return this.memory + processor;
            }
        }
    
        var noteBook = {
            memory: '16GB',
            storage: '2TB',
            videoMemory: '4GB',
            run: function(){
                return '你好,世界!';
            }
        }
        var Dell = new Computer(noteBook.memory, noteBook.storage, noteBook.videoMemory, noteBook.run);
        console.log(Dell);
        console.log(Dell.processor);
        console.log(Dell.run());
        console.log(Dell.introduce());
    
    • 构造函数中的return关键字
      • 构造函数中,return返回一个数组或对象等引用类型数据,则构造函数会直接返回该数据,而不会返回原来创建的对象。
      • 如果返回的是基本类型数据,则返回的数据无效,依然会返回原来创建的对象。
      • 总结:构造函数中的return只能返回引用类型的数组或对象,有合规的返回值返回数据,没有就返回本身的对象数据
        // 返回值是引用类型数据,返回对象本身
        var Computer = function(memory, storage, videoMemory, run){
            var processor = 'Core i7-4700MQ';
            this.memory = memory;
            this.storage = storage;
            this.videoMemory = videoMemory;
            this.run = run;
            this.introduce = function(){
                return this.memory + processor;
            }
            return {say:'你好,世界!'};
        }
    
        var Lenovo = new Computer();
        console.log(Lenovo);
    
        // 返回值是基本类型数据,返回数据无效,返回原来创建的对象
        var Computer = function(memory, storage, videoMemory, run){
            var processor = 'Core i7-4700MQ';
            this.memory = memory;
            this.storage = storage;
            this.videoMemory = videoMemory;
            this.run = run;
            this.introduce = function(){
                return this.memory + processor;
            }
            return 0;
        }
    
        var Lenovo = new Computer();
        console.log(Lenovo);
    

    内置对象

    • 定义:内置对象就是指这个语言自带的一些对象,供开发者使用,这些对象提供了一些常用的或是最基本而必要的功能。
      • Arguments 函数参数集合
      • Array 数组
      • Boolean 布尔对象
      • Date 日期时间
      • Error 异常对象
      • Function 函数构造器
      • Math 数学对象
      • Number 数值对象
      • Object 基础对象
      • RegExp 正则表达式对象

    String对象

    • String()对象
      • length - 获取字符串的长度
      • charAt(index) - 获取index位置的字符,位置从0开始计算
      • indexOf(searchValue) - 获取searchValue在字符串中首次出现的位置,没有返回-1
      • lastIndexOf(searchValue) - 获取searchValue在字符串中最后出现的位置,没有返回-1
      • substring(start[,end]) - 截取从start位置到end位置之间的一个子字符串
      • substr(start[,length]) - 截取从start位置开始到length长度的子字符串
      • toLowerCase() - 获取字符串的小写形式
      • toUpperCase() - 获取字符串的大写形式
      • split(separator[,limit]) - 使用separator分隔符将字符串分割成数组,limit用于限制数量
      • replace(str1,str2) - 使用str2替换字符串中的str1,返回替换结果
        var userName = function(name){
            var flag = 0;
            return function(){
                name.length<3 || name.length>15 ? console.log('用户名长度必须在3~10之间') : 
                    name.toLowerCase().indexOf('admin') !== -1 ? console.log('用户名中不能出现"admin"敏感词') :  
                        flag = 1;
                return flag;
            }
        }
    
        var newName = userName('dministrator');
        console.log(newName());
    

    Number对象

    • Number()对象
      • MAX_VALUE - 在JavaScript中所能表示的最大数值(静态成员)
      • MIN-VALUE - 在JavaScript中所能表示的最小正值(静态成员)
      • toFixed(digits) - 使用定点表示法来格式化一个数值
        var num = 12345.6789;
        num.toFixed();          // 12346
        num.toFixed(1);         // 12345.7
        num.toFixed(6);         //  12345.678900
        Number.MAX_VALUE;       // 1.7976931348623157e+308
        Number.MIN_VALUE;       // 5e-324
    

    Math对象

    • Math()对象:专门封装数学计算常用常量和计算方法的全局对象,Math没有构造函数,不能new!所有API都直接用Math.xxx,
      • Math.PI() - 获取圆周率,结果为3.141592653589793
      • Math.abs() - 获取x的绝对值,可传入普通数值或是用字符串表示的数值
      • Math.max([value1[,value2,...]]) - 获取所有参数中的最大值
      • Math.min([value1[,value2,...]]) - 获取所有参数中的最小值
      • Math.pow(base,exponent) - 获取基数(base)的指数(exponent)次幂
      • Math.sqrt(x) - 获取x的平方根
      • Math.ceil(x) - 获取大于等于x的最小整数,即向上取整
      • Math.floor(x) - 获取小于等于x的最大整数,即向上取整
      • Math.round(x) - 获取x的四舍五入后的整数值
      • Math.random() - 获取大于或等于0.0且小于1.0的随机数
        // 随机数函数
        var randomNum= function(min, max){
            if(arguments.length== 2){
                return Math.floor(Math.random()* (max- min+ 1)+ min);
                // return parseInt(Math.random()* (max- min+ 1)+ min);
            }else if(arguments.length== 1){
                return Math.ceil(Math.random()* min);
            }else{
                return Math.ceil(Math.random()* 100);
            }
        }
        console.log(randomNum());
    
        // 获得数组最大值
        Math.max.apply(Math,[1,2,3,4]);
    

    Date对象

    • Date()对象:封装一个1970年元旦至今的毫秒数(从1970年1月1日0点0分0秒到当前时间的毫秒差),提供了对时间操作的方法
      • get方法用来获得分量的值
        • getFullYear() - 获取表示年份的数字,如2020
        • getMonth() - 获取月份,范围0~11(0表示一月,1表示二月,以此类推)
        • getDate() - 获取月份中的某一天,范围1~31
        • getDay() - 获取星期,范围0~6(0表示星期一,1表示星期二,以此类推)
        • getHours() - 获取小时数,返回0~23
        • getMinutes() - 获取分钟数,范围0~59
        • getSeconds() - 获取秒数,范围0~59
        • getMilliseconds() - 获取毫秒数,范围0~999
        • getTime() - 获取从1970-01-01 00:00:00 距离Date对象所代表时间的毫秒数
      • set方法用来设置分量的值
        • setFullYear(value) - 设置年份
        • setMonth(value) - 设置月份
        • setDate(value) - 设置月份中的某一天
        • setHours(value) - 设置小时数
        • setMinutes(value) - 设置分钟数
        • setSeconds(value) - 设置秒数
        • setMilliseconds(value) - 设置毫秒数
        • setTime(value) - 通过从1970-01-01 00:00:00 计时的毫秒数来设置时间
    • 日期转字符串
      • var date = new Date();
      • date.toString() - GMT格式显示
      • date.toLocaleString() - 操作系统当地时间格式,包含时间和日期
      • date.toLocaleDateString() - 以操作系统当地时间格式,仅包含日期
      • date.toLocaleTimeString() - 以操作系统当地时间格式,仅包含时间
    • Date计算
      • 两日期对象可直接相减,结果是毫秒差!
      • 对每个分量做加减:3步: get分量值,做加减,set回去
      • 一步概括:date.setXXX(date.getXXX()+/-n);
        // 当前系统时间
        var date = new Date();
        // 2012年10月13日12时26分35秒
        var date = new Date(2012, 10, 13, 12, 26, 35);
        // 2012年10月有多少天
        var max = new Date(2012, 10, 0).getDate();
        // 获取当前月份
        var nowMonth = new Date().getMonth()+ 1;
        // 将毫秒数转化为时间
        var date = new Date(1499996760000);
        var dateTime = date.toLocaleString();
    
        // 1970年1月1日午夜以来的毫秒数
        new Date().getTime();   // 提倡使用的
        new Date().valueOf();
        Date.now();             // 直接使用的
        +new Date();            // 相当于隐式转换,将该元素转换成Number类型,如果转换失败,那么将得到 NaN
        new Date()* 1;          // +new Date() 将会调用 Date.prototype 上的 valueOf() 方法,根据MDN,Date.prototype.value方法等同于Date.prototype.getTime()
    
        // 实时时间
        setInterval(
            _=> {
                var date = new Date();
                var formate = (date=> {
                    var week = ['日', '一', '二', '三', '四', '五', '六'];
                    return date.getFullYear()+ '年'+ 
                            (date.getMonth()+ 1)+ '月'+ 
                            date.getDate()+ '日'+' ' + 
                            '星期'+ week[date.getDay()]+ ' '+ 
                            date.toLocaleTimeString();
                })(date);
                console.log(formate);
            },1000);
    

    错误处理与代码调试

    • 错误类型

      • Error - 表示普通错误,其余6种类型的错误对象都继承自该对象
      • EvalError - 调用eval()函数错误,已经弃用,为了向后兼容,低版本还可以使用
      • RangeError - 数值超出有效范围,如"new Array(-1)"
      • ReferenceError - 引用了一个不存在的变量,如"var a=1;a+b;"(变量b未定义)
      • SyntaxError - 解析过程语法错误,如"{;}" "if()" "var a=new;"
      • TypeError - 变量或参数不是预期类型,如调用了不存在的函数或方法
      • URIError - 解析URI编码出错,调用encodeURI()、escape()等URI处理函数时出现
    • 错误处理:发生错误时,保证程序不中断

        try{
            可能发生错误的代码
        }catch(err){//err中发生错误时会自动收到创建的error对象
            err.message: 保存了错误的详细原因
            err.name: 保存了错误对象的名称
        如果发生错误,才执行的错误处理代码
        }[finally{
        无论是否发生错误,都执行的代码
            *一定会在退出*之前*执行*
            一般释放用过的对象资源:xxx=null
        }]
    
    • 手动抛出错误对象
        try{
            // 创建错误对象
            var err = new Error('自定义错误信息');
            // 抛出错误对象
            // 也可以与上一行合并为:throw new Error('自定义错误信息');
            throw err;
        }catch(err){
            // 输出结果,自定义错误信息
            console.log(err.message);
        }
    
    • 执行效率

      • 如果可以提前预知错误的原因:建议使用if代替try catch
      • try中尽量少的包含代码,try的执行效率低,且多创建一个error对象
    • Source面板调试工具

      • Watch - 可以对加入监听列表的变量进行监听
      • Call Stack - 函数调用堆栈,可以在代码暂停时查看执行路径
      • Scope - 查看当前断点所在函数执行的作用域内容
      • Breakpoints - 查看断点列表
      • XHR Breakpoints - 请求断点列表,可以对满足过滤条件的请求进行断点拦截
      • DOM Breakpoints - DOM断点列表,设置DOM断点后满足条件时触发断点
      • Global Listeners - 全局监听列表,显示绑定在window对象上的事件监听
      • Event Listener Breakpoints - 可断点的事件监听列表,可以在触发事件时进入断点

    原型和原型链

    • 原型

      • 原型(prototype):保存所有子对象共有成员的对象
      • 每个构造函数都有一个原型属性,引用了该构造函数对应的原型对象
      • 由构造函数创建的每个对象中都有一个__proto__属性,指向构造函数的原型对象
      • 在访问子对象的成员时,优先在成员本地找,找不到,再去构造函数的原型中查找
    • 创建原型

      • 创建空对象
      • 调用构造函数,为新对象添加成员
      • 设置当前对象的__proto__属性为构造函数的原型对象
      • 每个对象自有的成员,放在构造函数中
      • 所有子对象共有的成员,放在原型对象中
    • 原型链

      • 由各级对象的__proto__逐级向上引用形成的多级继承关系
      • 所有的对象都有一个__proto__属性,指向自己的父对象
    • 原型相关API

      • 判断一个属性是否可用
        • in关键字:"属性名" in 对象
          • 如果"属性名"在当前对象的原型链中,返回true
          • 如果在整条原型链上都没找到,返回false
        • 使用===undefined:说明不包含
          • 简写为(!对象.成员名)
        • 判断是否自有属性:
          • obj.hasOwnProperty("成员");
          • 如果obj本地有指定"成员",则返回true,没有返回false
        • 判断共有属性:
          • 不是自有的,还要存在于原型链上
          • if(!obj.hasOwnProperty("成员")&&"成员" in obj)
      • 获得任意对象的__proto__属性:
        • 获得父级对象
        • var 父对象=Object.getPrototypeOf(对象);
      • 判断父对象是否处在子对象原型链的上级:
        • 父对象.isPrototypeOf(子对象);
        • 只要父对象在子对象的原型链上,就返回true,否则返回false
      • 删除对象中的属性:
        • delete 对象.成员
        • 只能删除自有的成员
        • 只有var声明的全局变量不让delete
        • 使用window.或window[""]增加的全局成员可以delete
      • 判断一个对象是数组的几种方法
        • Array.prototype.isPrototypeOf(obj)
          • 如果返回true,说明是数组,否则不是
        • obj instanceof Array
          • 对象 instanceof 类型名,返回true,说明是数组
          • instancof会查找原型链上所有原型的构造函数
        • Object.getPrototypeOf(obj)==Array.prototype
        • Object.prototype.toString.call(arr)
          • override,子对象觉得父对象的成员不好用
          • 可自己定义同名的自有成员覆盖父对象
        • Object.prototype.toString.apply(arr)
          • call和apply: 在调用方法的一瞬间,替换调用方法的对象
        • Array.isArray(obj)
          • 专门判断对象是否是数组!

    继承

    • 概念

      • 通过【某种方式】让一个对象可以访问到另一个对象中的属性和方法,我们把这种方式称之为继承 并不是所谓的xxx extends yyy
      • 有些对象会有方法(动作、行为),而这些方法都是函数,如果把这些方法和函数都放在构造函数中声明就会导致内存的浪费
    • 继承的第一种方式:原型链方法继承

        var Person = function(){
            
        };
        Person.prototype.say=function(){
            console.log("你好")
        }
        var sunny = new Person();
        console.log(sunny.say());
    
    • 继承的第二种方式:原型链继承
        // 一般情况下,应该先改变原型对象,再创建对象;
        // 一般情况下,对于新原型,会添加一个constructor属性,从而不破坏原有的原型对象的结构;
        var Person = function(){};
        Person.prototype = {
            //切记不能忘记
            constructor:Person,
            say:function(){
                console.log("你好");
            },
            run:function(){
                console.log("正在进行百米冲刺");
            }
        }
        var sunny = new Person;
        sunny.say();
        console.log(Person.prototype.constructor === Person);
    
    
    • 继承的第三种方式:拷贝继承(混入继承:mixin)
        // 由于拷贝继承在实际开发中使用场景非常多,所以很多库都对此有了实现
        // jquery:$.extend
        var Person = {
            hear: 'black',
            skin: 'yellow',
            eye: 'brown',
        }
        var extend = function (source){
            let target = {};
            for(let key in source){
                target[key] = source[key];
            }
            return target;
        }
        var sunny = extend(Person);
        sunny.hear = 'white';
        console.log(sunny);
    
        // es6中有了 <对象扩展运算符> 仿佛就是专门为了拷贝继承而生
        var Person = {
            hear: 'black',
            skin: 'yellow',
            eye: 'brown',
        }
        var target = {...Person}; 
        console.log(target);
    
    • 继承的第四种方式:原型继承 (道格拉斯在蝴蝶书中提出来的)
        var Person = {
            hear: 'black',
            skin: 'yellow',
            eye: 'brown',
        }
        var sunny = Object.create(Person);
        console.log(sunny.__proto__);
    
    • 继承的第五种方式:借用构造函数实现继承
        var Animal = function(name, age){
            this.name = name;
            this.age = age;
        }
        var Person = function(name, age, address){
            Animal.call(this, name, age);
            this.address = address;
            return this.age;
        }
        console.log(Person('dog', '18', '不告诉你!'));
    
  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 字符串逆序
    Java实现 蓝桥杯VIP 算法训练 字符串逆序
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 成绩的等级输出
    Java实现 蓝桥杯VIP 算法训练 成绩的等级输出
    Qt 自定义model实现文件系统的文件名排序
  • 原文地址:https://www.cnblogs.com/SharkJiao/p/13548186.html
Copyright © 2011-2022 走看看