JS进阶(四)面向对象

简介: 面向对象1、对象、类、实例JS 本身是基于面向对象思想设计出来的一门编程语言,当我们给予JS进行程序设计的时候,也应该按照面向对象的想法去开发或者理解。对象,一种泛指类:对象的一部分实例:某个类中的具体事物

面向对象

1、对象、类、实例

JS 本身是基于面向对象思想设计出来的一门编程语言,当我们给予JS进行程序设计的时候,也应该按照面向对象的想法去开发或者理解。

对象,一种泛指

类:对象的一部分

实例:某个类中的具体事物

2、内置类

【数据类型】

  • Number 、 String、 Boolean 、 (Symbol、BigInt)
  • Object、Array、RegExp、Date...
  • Function

【每一个元素对象都有一个自己所属的类】

  • HTMLHtmlElement / HTMLBodyElement / HTMLDivElement
  • HTMLElement  XMLElement HTMLDocument

dir(document)

【元素/节点/样式/集合】

Document.getElemrntsByTagName("*")

Window.getComputedStyle(document.body)

3、 自定义类

自定义类,创建自定义类的实例

function Func(x,y){
   let total = x + y;
   this.result = total;
   this.say = function(){}
   return 10   // 返回基本类型,new时还是他的实例
}
// 普通函数执行
let f = Func(10,20);  // undefined
result // 30
/* 构造函数执行
 * 执行时,new一个函数,此时函数称为自定义类,一般返回值被称为当前一个类的实例,特殊情况
 */
let f = new Func(10,20)
// f => Func {result: 30}
let f1 = new Func
let f2 = new Func
f1.say === f2.say  // false
// 验证某个属性是否为当前对象的属性
// + in 验证私有公有属性都可以
// + hasOwnProperty 验证私有属性
// instanceof 检测当前实例是不是属于某个类

分析构造函数执行做了哪些事情

三句话玩转面向对象
1、每一个函数类型(构造函数(类)),天生具备一个属性"prototype原型",属性值是一个对象,存储当前类的公共属性和方法。供实例来调用。
2、在原型对象上有一个内置的属性"constructor"构造函数,存储的值是当前函数本身,所以把类称为构造函数
3、每一个对象都天生具备一个属性,"__proto__隐式原型/原型链属性", 属性值指向自己所属类的原型对象(实例的.__proto__ = 所属类的.prototype)
函数类型
 - 普通函数
 - 构造函数(类)
 - 所有内置类都是一个函数 Object、Function..
   > typeof Number , typeof Object. 'function' 
对象类型
 - prototype/__proto__
 - 函数也是对象
 - 类的实例也是对象(排除基本数据类型值的特殊性)
 - 万物皆对象

// Object.create([Object])
创建一个空对象,并且把[Object]对象作为新空对象的原指向
// x.__proto__ = [Object]
创建一个没有原型/原型链的对象 不是任何的实例
// Object.create(null)
// Object.create 不兼容低端浏览器
// 我们写的这个方法不支持null的处理
Object.create = function create(prototype){
  if(prototype ===null || typeof prototype==='object'){
    throw new TypeError(`Object prototype may only be an Object or null: ${prototype}`)
  }
  // 创建一个类,创建这个类的实例,实例.__proto__ = 类.prototype 我们让类prototype等于传递的prototype
  function Temp(){}
  Temp.prototype = prototype;
  return new Temp
}
// 实现一个自定义new
function Dog(name){
  this.name = name;
}
Dog.prototype.brak = function (){
  console.log('wangwang')
}
Dog.prototype.sayName = function (name){
  console.log('my name is'+name)
}
 /*
  * Func要操作这个类(最后创建这个类的实例)
  * args存储未来传递给Func类的实参
  */
function _new(Func,...args){
    // 1、创建一个Func的实例对象,(实例的.__proto__应该指向类的.prototype)
    // 因为在ie浏览器中,禁止我们使用__proto__(IE没有暴露这个方法,防止我们去改变原型指向), 
    /* 
    let obj = {};
    obj.__proto__ = Func.prototype;
    */
    let obj = Object.create(Func.prototype)
    // 2、把Func当普通函数执行,(让方法中的this指向创建的实例)
    let result = Func.call(obj,...args);
    // 3、分析函数执行的返回值,没有返回值或者返回的是原始类型的值,默认都返回创建的实例,否则以函数自身返回的为主
    if(result !==null && /^(object|function)$/.test(typeof result)){
      return result
    }
    return obj
}
let sanmao = _new(Dog,'三毛')
sanmao.brak()   // 'wangwang'
sanmao.sayName('sanmao')  // 'my name is sanmao'
console.log(sanmao instanceof Func) // true

4、 This 的五种情况

/*
     * THIS:执行主体(谁把他执行的),所以THIS和执行上下文不是一个东西
     * 
     * 如何区分执行主体:和函数在哪执行和创建没有必然的关系
     *    1. 函数执行,看函数前看是否有“点”,有“点”它前面是谁THIS就是谁,没有“点”THIS就是window(非严格模式)/undefined(严格模式)
     *       + 自执行函数中的THIS一般都是window/undefined
     *       + 回调函数中的THIS一般也是window/undefined(除非某个函数内部给回调函数做了特殊的处理,这样回调函数中的THIS有自己的特殊情况)
     *    2. 给当前元素的某个事件行为绑定方法,当事件行为触发,方法中的THIS是当前操作的元素(特殊:IE6~8中基于DOM2事件绑定attachEvent,方法中的this不是元素)
     *    3. 箭头函数中(私有块级上下文)没有自己的THIS,所用到的THIS都是其上级上下文中的THIS(也就是没有初始化THIS这一步)
     *    4. 构造函数中的THIS一般是当前类的实例
     *    5. 基于call/apply/bind可以强制改变THIS
     */
    // console.log(this);  //=>window
    /* (function () {
      console.log(this); //=>window
    })(); */
    /* setTimeout(function () {
      console.log(this); //=>window
    }, 0); */
    /* let obj = {
      fn: (function () {
        // this => window
        return function () {
          console.log(this);
        }
      })() //把自执行函数执行的返回值赋值给fn属性(自执行函数只有给fn赋值的时候执行一次,后期执行obj.fn()执行的是返回的小函数)
    };
    obj.fn(); //this=>obj
    let fn = obj.fn;
    fn(); //this=>window */
    /* var fullName = 'language';
    var obj = {
      fullName: 'javascript',
      prop: {
        getFullName: function () {
          return this.fullName;
        }
      }
    };
    console.log(obj.prop.getFullName());
    // this -> obj.prop
    // obj.prop.fullName => undefined
    var test = obj.prop.getFullName;
    console.log(test());
    // this -> window
    // window.fullName => 'language' */
    /* var name = 'window';
    var Tom = {
      name: "Tom",
      show: function () {
        // this -> window
        console.log(this.name); //=>'window'
      },
      wait: function () {
        // this -> Tom
        var fun = this.show;
        fun();
      }
    };
    Tom.wait(); */
    /* window.val = 1;
    var json = {
      val: 10,
      dbl: function () {
        this.val *= 2; // this.val=this.val*2
      }
    }
    json.dbl();
    // this -> json
    // json.val=json.val*2=20
    var dbl = json.dbl;
    dbl();
    // this -> window
    // window.val=window.val*2=2
    json.dbl.call(window);
    // this -> window
    // window.val=window.val*2=4
    alert(window.val + json.val); //=>"24" */
    /* (function () {
      // this -> window
      var val = 1;
      var json = {
        val: 10,
        dbl: function () {
          val *= 2; // val=val*2  
          // val是一个变量,让自执行函数中的私有变量val=2
        }
      };
      json.dbl();
      alert(json.val + val); //=>"12"
    })(); */
    /* var num = 10;
    var obj = {
      num: 20
    };
    obj.fn = (function (num) {
      this.num = num * 3;
      num++;
      return function (n) {
        this.num += n;
        num++;
        console.log(num);
      }
    })(obj.num);
    var fn = obj.fn;
    fn(5);
    obj.fn(10);
    console.log(num, obj.num); */

5、实现一个new操作符

// Func要操作的这个类(最后要创建这个类的实例)
    // ARGS存储未来传递给Func类的实参
    function _new(Func, ...args) {
      // 1.创建一个FUNC的实例对象(实例.__proto__=>类.prototype)
      // 在IE浏览器中,禁止我们使用__proto__(也可以理解为IE并没有提供给我们__proto__这个属性,防止我们去改变原型指向)
      /* let obj = {};
      obj.__proto__ = Func.prototype; */
      let obj = Object.create(Func.prototype);
      // 2.把FUNC当做普通函数执行(让方法中的THIS指向创建的实例)
      let result = Func.call(obj, ...args);
      // 3.分析函数执行的返回值(没有返回值或者返回的是原始值类型则默认都返回创建的实例,否则以函数自身返回的为主)
      if (result !== null && /^(object|function)$/.test(typeof result)) {
        return result;
      }
      return obj;
    }
    let sanmao = _new(Dog, '三毛');
    sanmao.bark(); //=>"wangwang"
    sanmao.sayName(); //=>"my name is 三毛"
    console.log(sanmao instanceof Dog); //=>true

相关文章
|
5月前
|
前端开发 JavaScript 开发者
JavaScript进阶-Promise与异步编程
【6月更文挑战第20天】JavaScript的Promise简化了异步操作,从ES6开始成为标准。Promise有三种状态:pending、fulfilled和rejected。基本用法涉及构造函数和`.then`处理结果,如: ```javascript new Promise((resolve, reject) => { setTimeout(resolve, 2000, '成功'); }).then(console.log); // 输出: 成功
85 4
|
5月前
|
存储 JavaScript 前端开发
JavaScript进阶-Map与Set集合
【6月更文挑战第20天】JavaScript的ES6引入了`Map`和`Set`,它们是高效处理集合数据的工具。`Map`允许任何类型的键,提供唯一键值对;`Set`存储唯一值。使用`Map`时,注意键可以非字符串,用`has`检查键存在。`Set`常用于数组去重,如`[...new Set(array)]`。了解它们的高级应用,如结构转换和高效查询,能提升代码质量。别忘了`WeakMap`用于弱引用键,防止内存泄漏。实践使用以加深理解。
74 3
|
4月前
|
XML 前端开发 JavaScript
JavaScript进阶 - AJAX请求与Fetch API
【7月更文挑战第3天】前端开发中的异步基石:AJAX与Fetch。AJAX,使用XMLHttpRequest,处理跨域、回调地狱和错误处理。Fetch,基于Promise,简化请求,但需注意默认无跨域头和HTTP错误处理。两者各有优劣,理解其问题与解决策略,能提升前端应用的性能和用户体验。
127 24
|
5月前
|
设计模式 JavaScript 前端开发
【JavaScript】深入浅出JavaScript继承机制:解密原型、原型链与面向对象实战攻略
JavaScript的继承机制基于原型链,它定义了对象属性和方法的查找规则。每个对象都有一个原型,通过原型链,对象能访问到构造函数原型上的方法。例如`Animal.prototype`上的`speak`方法可被`Animal`实例访问。原型链的尽头是`Object.prototype`,其`[[Prototype]]`为`null`。继承方式包括原型链继承(通过`Object.create`)、构造函数继承(使用`call`或`apply`)和组合继承(结合两者)。ES6的`class`语法是语法糖,但底层仍基于原型。继承选择应根据需求,理解原型链原理对JavaScript面向对象编程至关重要
114 7
【JavaScript】深入浅出JavaScript继承机制:解密原型、原型链与面向对象实战攻略
|
4月前
|
前端开发 JavaScript 安全
JavaScript进阶-JavaScript库与框架简介
【7月更文挑战第11天】JavaScript库和框架加速Web开发,但也带来挑战。选择适合项目、团队技能的库或框架,如React、Angular、Vue,是关键。保持依赖更新,注意性能优化,避免过度依赖。遵循最佳实践,确保安全性,如防XSS和CSRF。学习基础,结合代码示例(如React计数器组件),提升开发效率和应用质量。
55 1
|
4月前
|
缓存 JavaScript 前端开发
JavaScript进阶 - Web Workers与Service Worker
【7月更文挑战第4天】JavaScript的Web Workers和Service Worker增强了Web性能。Web Workers处理后台多线程,减轻主线程负担,但通信有开销,受同源策略限制。Service Worker则用于离线缓存和推送通知,需管理其生命周期、更新策略,并确保安全。两者都带来了挑战,但也极大提升了用户体验。通过理解和优化,开发者能构建更高效、安全的Web应用。
110 2
|
4月前
|
资源调度 JavaScript 前端开发
JavaScript进阶 - JavaScript库与框架简介
【7月更文挑战第5天】JavaScript库和框架构成了前端开发的核心,如jQuery简化DOM操作,Angular、React和Vue提供全面解决方案。选择时要明确需求,避免过度工程化和陡峭学习曲线。使用版本管理工具确保兼容性,持续学习以适应技术变化。示例展示了jQuery和React的简单应用。正确选择和使用这些工具,能提升开发效率并创造优秀Web应用。
47 2
|
4月前
|
设计模式 前端开发 JavaScript
JavaScript进阶 - JavaScript设计模式
【7月更文挑战第1天】JavaScript设计模式增进代码复用和维护性。单例模式确保唯一实例,用闭包防止命名冲突和控制状态访问。观察者模式实现一对多依赖,通过解绑避免内存泄漏。工厂模式封装对象创建,适度使用避免复杂度。装饰者模式动态添加行为,保持简洁以保可读性。理解模式的优缺点,灵活应用,提升代码质量。
128 3
|
4月前
|
存储 前端开发 安全
JavaScript进阶 - 浏览器存储:localStorage, sessionStorage, cookies
【7月更文挑战第2天】探索Web存储:localStorage持久化,sessionStorage会话限定,cookies则伴随HTTP请求。了解它们的特性和限制,如localStorage的5MB容量限制、跨域问题,sessionStorage的生命周期,及cookies的安全与带宽消耗。使用时需权衡安全、效率与应用场景。示例代码展示存储与检索方法。
231 2
|
5月前
|
JavaScript 前端开发
JavaScript进阶-Class与模块化编程
【6月更文挑战第21天】**ES6引入Class和模块化,提升JavaScript的代码组织和复用。Class是原型机制的语法糖,简化面向对象编程。模块化通过`import/export`管理代码,支持默认和命名导出。常见问题包括`this`指向和循环依赖。理解这些问题及避免策略,能助你写出更高效、可维护的代码。**
62 5