资讯专栏INFORMATION COLUMN

javascript基础学习

魏明 / 394人阅读

摘要:预解释变量和函数的预解释只发生在当前的作用于中中内存的分类栈内存用来提供一个代码指定的环境作用域全局作用域和局部作用域堆内存用来存储引用类型的值对象存储的是键值对,函数储存的是字符串函数执行的时候形成一个私有作用域有形参给形参赋值,形参也

预解释

变量和函数的预解释只发生在当前的作用于中

js中内存的分类

栈内存:用来提供一个js代码指定的环境 —>作用域(全局作用域和局部作用域)

堆内存:用来存储引用类型的值 ->对象存储的是键值对,函数储存的是字符串

函数执行的时候形成一个私有作用域

1.有形参给形参赋值,形参也是函数的局部变量,把实参赋值一份给形参(值类型和引用类型不同的情况)2.进行私有作用域预解释 3.私有作用域从上倒下执行

作用链的机制:冒泡向上查找(作用域链模式查找)

闭包: 函数形成了一个新新的私有作用域保护了里面的私有作用域不受外界的干扰(外界改变不了私有的,私有的也改变不了外面的)

函数不使用var声明的变量,指定函数时是绑定到window上的

预解释的时候,不管条件成立不成立都会进行预解释

在js中如果变量的名字和函数的名字重复了,也算冲突

如何查找当前作用域上一级作用域?看当前的函数是在那个作用域定义的,和执行没有关系

内存的释放和作用域销毁

堆内存:

对象数据类型或者函数数据类型在定义的时候首先开辟一个堆内存,对内存有一个引用地址,如果外面有变量知道了这个地址,我们就说这个内存被占用了,就不能销毁

我们想要让堆内存释放/销毁,只需要把所有她的变量设置为null即可,如果当前的堆内存没有任何东西被占用,那么浏览器会在空闲的时候把它销毁...

栈内存

全局作用域

私有作用域(只有函数执行才能产生私有作用域)

一般情况下,函数执行会形成一个私有的作用域,当私有作用域执行完成后,都会主动的释放和销毁(即函数执行时开辟内存空间,执行完成后内存空间会被释放和销毁)

特殊情况下,当前私有作用域中的部分内存被作用域以为的变量占用了,那么当前的作用域就不能销毁了(地址被其他占用,就不能够销毁)

   function fn () {
       var num = 100;
       return function () {

       }
   }
   var f = fn()  // 私有作用域被外界占用不会销毁
   fn()()  // 不立即销毁私有作用域,当返回的函数执行执行完毕后,再销毁

自执行函数形成的作用域也不会销毁(dom的click绑定函数也会占用作用域以外的内存,私有作用域也不会销毁)

  ~function () {
      oDiv.onclick = function () {
          .... //原理都是一样的,都是函数地址被别的占用不销毁
      }
  }

js中的this

js中的this主要是函数中函数的this

js中的this代表当前执行的主体,js的contenxt代表的是当前的执行环境(this和执行上下文没必然的联系)

this是谁和函数在哪定义和在哪执行没有必然的联系

this在函数中5种情况

函数执行,首先看函数名之前,有没有.,有点.的话之前是谁,this就是谁

 function fn() {
     console.log(this)
 }
 var obj = {fn:fn};
 obj.fn() // this 指向fn
 function sum (){
     fn()
 }
 sum() // this指向window
 var o = {
     sum: function () {
         fn() 
     }
 }
 o.sum() // this指向window

自执行函数中的this永远指向window

给元素的某一个事件绑定一个方法,当事件触发的时候,执行对应的方法,方法中的this是当前的元素

document.getElementById("#app").onclick = function(){
    console.log(this)  // this ->app元素对象
    fn()  // this指向window
}

在构造函数当中,类中(函数体中)出现的this指向当前new创建的实例

设计模式

单利模式

对象数据类型:把同一个事物的属性和方法放在同一个孔家下,起到了分组的作用,不同事物之间的属性即使属性名相同,也不会发生冲突,这种分组编写代码的模式叫做单利模式(模块化开发的原理)

缺点: 单利模式不能够批量生产

工厂模式

把实现同一件是事情的相同代码放在一个函数中,以后如果想实现这个功能,不需要重新在编写这个代码,直接调用函数即可 --> 函数的封装

缺点:不能够识别调用者的身份

  function createPerson (name, age) {
      var obj = {};
      obj.name = name;
      obj.age = age;
      obj.call = function() {
          ....
      }
      return obj
  }

构造函数模式

构造函数目的:就是为了创建一个自定义类

  function createPerson (name, age) {
      var obj = {};
      obj.name = name;
      obj.age = age;
      obj.call = function() {
          ....
      }
      return obj
  }
   function CreatePerson (name, age) {
       
      this.name = name;
      this.age = age;
      this.call = function() {
          ....
      }
  }
  var p1 = new createPerson("章三", 18)

工厂函数和构造函数的区别

执行的时候

普通函数执行 --> createPerson()

构造函数执行 ——> new createPerson() // 通过new创建出来一个实例(p1)

在函数执行的时候

相同点: 都是形成一个私有的作用域,然后形参赋值 ->预解释 ->代码自上而下执行

不同点:构造函数在代码执行之前,不用再手动创建对象(new的作用)

1.浏览器会默认创建一个对象(而这个对象就是我们new创建出来的实例),

2.然后把属性值和属性名赋值给当前的实例,

3.最后浏览器会把创建的这个实例返回

检测数据类型的方式:

typeof(): 检测基本的数据类型

instanceof():检测某一个实例是否属于这个类

attr in Obj: 检测某一个属性(共有和私有)是否属于这个对象

hasOwnProperty: 用来检测一个私有属性是够属于这个对象

原型模式

基于构造函数的圆形模式解决了方法和属性共有的问题

1.每一个函数类型(函数,类)都有一个天生自带的属性:prototype,并且这个属性是一个对象数据类型的值

并且在prototype上天生给他加了一个属性constructor(构造函数),属性值是当前函数本身

3.每一个对象数据类型(普通独享,实例,prototype...)也天生自带一个属性:__proto__,属性值是当前实例所属类或函数的原型(prototype)

function Fn() {
     this.x = 100
}
Fn.prototype.add = function () {
     console.log(this.x)
}
var f1 = new Fn();
var f2 = new Fn();
f1.hasOwnproperty("x")

Object是所有对象类型的基类

在Object.prototype上是没有__proto__属性(是唯一没有的)

再实例对象f1上没有hasOwnProPerty这个属性?

通过对象名.属性名 的形式获取属性值的时候,首先在对象的私有属性进行查找,若果私有中存在这个属性,则获取这个私有属性值;若果没有,通过__proto__找到所属类的原型(具有类原型定义的公共方法和属性),原型存在的,获取共有的属性值;如果原型上也没有,则继续通过原型的__proto__继续查找,直到找到Object.prototype为止,这种查询模式叫做"原型链模式"

原型链模式遵行冒泡形式就近原型

所有类都是函数数据类型的,所有类的原型都是对象数据类型的

Fuction函数类,所有的函数数据类型都是它的一个实例

再内置类原型上扩展我们的方法

Array.prototype.mgUnique = function(){
    var obj = {}
    for(var i=0;i

批量添加共有方法

   function Fn(){
       this.x = 100
   }
   Fn.prototype = { // 重构原型的指向
       constructor: Fn, // 手动添加constructor
       a: function(){
           ...
       },
       b:function(){
           ...
       }
   }

克隆一个对象的方式

原生实现

  function cloneObj(obj){
      var obj2 = {};
      for(var key in obj) {
          if(obj.hasOwnproperty(key)){
              obj2[key] = obj[key]
          }
      }
      retuen obj2
  }

Object.create(proObj): 创建一个新的对象,把proObj当作新创建对象的原型,IE8下不兼容

  function object(o){
      function Fn(){

      }
      Fn.prototype = o;
      return new Fn;
  }

1.原型继承

B.prototype = new A;

原型链继承的特点:子类B继承了父类A所有的属性和方法

   #div.__proto__ -> HTMLDivElement.prototype ->
   HTMLElement.prototype ->Element.prototype ->
   Node.prototype ->EventTarget.prototype ->
   Object.prototype(Dom原型继承的原理)

   function Object() {
       ...
   }
   Object.prototype = {
       constructor:Object,
       hasOwnProperty: function(){
           ...
       }
   };
   function EventTarget () {
       ...
   }
   
   EventTarget.prototype = new Object();
   EventTarget.prototype.addEventListenter = function(){
       ...
   }
   function Node(){
       ...
   }
   Node.prototype = new EventTarget();
   Node.prototype.createElement = function(){
       ...
   }

原型继承并不是把父类中的属性和方法克隆一份给子类,而是让子类和父类增加了原型链的链接,哟吼子类获取父类的方法,需要一级一级的向上查找来使用

2. call继承

把父类的私有方法和属性克隆一份,作为子类的私有属性

  function A(){
      this.x = 100;
  }
  A.prototype.getX = function(){
      console.log(this.x)
  }
  function B(){
      
      A.call(this) // A.call(n) 把修改this的指向,并让A执行
  }
  var n = new B()

3.冒充对象继承 4.混合模式继承

原型继承+call继承

    function A(){
        this.x = 100;
    }
    A.prototype.getX = function(){
        console.log(this.x)
    }
    function B(){
        
        A.call(this) // A.call(n) 把修改this的指向,并让A执行
    }
    B.prototype = new A;
    B.prototype.constaructor = B
    var n = new B()

5.寄生混合式继承
    function A(){
        this.x = 100;
    }
    A.prototype.getX = function(){
        console.log(this.x)
    }
    function B(){
        
        A.call(this) // A.call(n) 把修改this的指向,并让A执行
    }
    B.prototype = Object.create(A.prototype);
    B.prototype.constaructor = B
    var n = new B()
函数的三种角色
 function Fn(){
     var num = 500;
     this.x = 100;
 }
 Fn.prototype.getX = function(){
   console.log(this.x)
 }
 Fn.aaa = 1000;
 var f = new Fn();
  f.num  // undefined
  f.aaa // undefined
  var res = Fn() // this指向undefined
  Fn.aaa  // 1000

函数在整个js中是最复杂也是最重要的知识

一个函数存在了多面性

普通函数:本身就是一个函数,执行的时候形成私有的左右域(闭包),形参赋值,预解释,代码执行,执行完成后内存销毁/不销毁

类:它有自己的实例,也有一个叫prototype属性是自己的原型,它的实例都可以通过__proto__指向自己的原型

普通对象:和 var obj = {}中的obj一样,就是一个普通对象,他作为对象可以有一些自己的私有属性,也可以通过__proto__找到Function.prototype对象

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/108775.html

相关文章

  • 基础巩固:JavaScript基础总结(基本概念篇)

    摘要:基础巩固基础总结使用已经好几年了,由于工作主要是做服务端开发,在工作中逐渐发现的使用范围原来越广泛。这里要注意,务必将基础部分掌握牢靠,磨刀不误砍柴功,只有将基础部分掌握并建立起系统的知识体系,在后面学习衍生的其他模式才能游刃有余。 基础巩固:JavaScript基础总结 使用JavaScript已经好几年了,由于工作主要是做服务端开发,在工作中逐渐发现JavaScript的使用范围原...

    YuboonaZhang 评论0 收藏0
  • 程序员练级攻略(2018):前端基础和底层原理

    摘要:下面我们从前端基础和底层原理开始讲起。对于和这三个对应于矢量图位图和图的渲染来说,给前端开发带来了重武器,很多小游戏也因此蓬勃发展。这篇文章受众之大,后来被人重新整理并发布为,其中还包括中文版。 showImg(https://segmentfault.com/img/bVbjM5r?w=1142&h=640); 想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你! 这...

    widuu 评论0 收藏0
  • 2019年前端学习路线

    摘要:也就是我们常见的浏览器以及内置浏览器,比如微信打开的大型移动端网页。这个以微信小程序为例,主要是微信团队基于前端基础来做的封装语法,主要的还是语法。学习路线放一下给大家。前端开发学习不是单一的,内容比较多,同样应用的场景也非常多。 近两年来,前端开发工程师越来越火了,2019年已经到来了,很多准备入行前端开发工程师的小伙伴们,不知道准备得怎么样了呢?有的朋友在想方设法的学习,争取在年后...

    cfanr 评论0 收藏0
  • 2019年前端学习路线

    摘要:也就是我们常见的浏览器以及内置浏览器,比如微信打开的大型移动端网页。这个以微信小程序为例,主要是微信团队基于前端基础来做的封装语法,主要的还是语法。学习路线放一下给大家。前端开发学习不是单一的,内容比较多,同样应用的场景也非常多。 近两年来,前端开发工程师越来越火了,2019年已经到来了,很多准备入行前端开发工程师的小伙伴们,不知道准备得怎么样了呢?有的朋友在想方设法的学习,争取在年后...

    Miracle_lihb 评论0 收藏0
  • 2019年前端学习路线

    摘要:也就是我们常见的浏览器以及内置浏览器,比如微信打开的大型移动端网页。这个以微信小程序为例,主要是微信团队基于前端基础来做的封装语法,主要的还是语法。学习路线放一下给大家。前端开发学习不是单一的,内容比较多,同样应用的场景也非常多。 近两年来,前端开发工程师越来越火了,2019年已经到来了,很多准备入行前端开发工程师的小伙伴们,不知道准备得怎么样了呢?有的朋友在想方设法的学习,争取在年后...

    zhoutk 评论0 收藏0

发表评论

0条评论

魏明

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<