步入放羊之web-js

作用域

局部作用域

  • 局部作用域分为函数作用域和块级作用域

函数作用域

  • 在函数内部声明的变量只能在函数内部被访问,外部无法直接访问

    xml 复制代码
      <script>
        // 声明 counter 函数
        function counter(x, y) {
          // 函数内部声明的变量
          const s = x + y
          console.log(s) // 18
        }
        // 设用 counter 函数
        counter(10, 8)
        // 访问变量 s
        console.log(s)// 报错
      </script>
  • 函数的参数也是函数内部的局部变量

  • 不同函数内部声明的变量无法互相访问

  • 函数执行完毕后,函数内部的变量实际被清空了

块级作用域

  • 在JS中使用{}包裹的代码块称为块级作用域,代码块内部声明的变量外部将【有可能】无法被访问
  • let声明的变量会产生块作用域,var不会产生块作用域
  • const声明的常量也会产生块作用域
  • 不同代码块之间的变量无法互相访问

闭包

  • 函数内部返回的函数使用了函数内部顶层的参数

  • 在函数执行完毕后,函数内部参数和内部包含的函数不会被立刻释放,内部函数依旧可以打印

  • 闭包可以实现数据私有但可能引起内存泄漏

  • 使用场景如计数器:

    scss 复制代码
          function fn1() {
            let count = 0
            const fn2 = ()=>{
              count++
              console.log(count)
            }
            return fn2
          }
          let f = fn1()
          f()
          f()
          f()
          f()
          

var let const

  • var定义的变量和规范function定义的会产生变量提升

    xml 复制代码
      <script>
        // 调用函数
        foo()
        // 声明函数
        function foo() {
          console.log('声明之前即被调用...')
        }
    
        // 不存在提升现象
        bar()  // 错误
        var bar = function () {
          console.log('函数表达式不存在提升现象...')
        }
      </script>
  • 例如var a = 1;只将var a提升,赋值不提升

  • let const不会产生变量提升

    javascript 复制代码
         obj.fn()
         function func(){
            console.log(this.a)
          }
          const obj ={
            a:1,
            fn:function(){
              console.log(this)
              func()
            }
          }
          var a = 2
          等价于
         var a
         function func(){
            console.log(this.a)
          }
          const obj ={
            a:1,
            fn:function(){
              console.log(this)
              func()
            }
          }
          a = 2 
          obj.fn()

this

  • 全局this是指向window对象

    scss 复制代码
      function fn() {
        console.log(this)
      }
      fn()//window
  • 谁调用this就指向谁

    javascript 复制代码
        function fn1() {
        console.log(this)
      }
      let obj = {
        fn1:fn1
      }
      obj.fn1()//obj
      
           function func(){
            console.log(this.a)
          }
          const obj ={
            a:1,
            fn:function(){
              console.log(this)
              func()
            }
          }
          var a = 2
          obj.fn()//obj 
  • 定时器的this永远指向window(不管谁调用)

    javascript 复制代码
      const obj = {
        fn:function(){
          console.log(this)
        }
      }
      setTimeout(obj.fn,1000)//window
  • 箭头函数的this永远指向上一个正常function指向的this

    javascript 复制代码
      var name = 'tom'
      const obj = {
          name: 'zc',
          intro:function ()  {
              return () => {
                  console.log('My name is ' + this.name)
              }
          },
          intro2:function ()  {
              return function() {
                  console.log('My name is ' + this.name)
              }
          }
      }
      obj.intro2()()//my name is tom
      obj.intro()()//my name is zc

函数参数

动态参数arguments

  • arguments是一个伪数组

  • arguments的作用是动态获取函数的实参

    scss 复制代码
      <script>
        // 求和函数,计算所有参数的和
        function sum() {
          // console.log(arguments)
          let s = 0
          for(let i = 0; i < arguments.length; i++) {
            s += arguments[i]
          }
          console.log(s)
        }
        // 调用求和函数
        sum(5, 10)// 两个参数
        sum(1, 2, 4) // 两个参数
      </script>

剩余参数...

  • ...是语法符号,置于最末函数形参之前,用于获取多余的实参

  • 借助...获取的剩余实参是个真数组

    xml 复制代码
      <script>
        function config(baseURL, ...other) {
          console.log(baseURL) // 得到 'http://baidu.com'
          console.log(other)  // other  得到 ['get', 'json']
        }
        // 调用函数
        config('http://baidu.com', 'get', 'json');
      </script>

箭头函数

  • 箭头函数属于表达式函数,不存在函数提升

  • 箭头函数只有一个参数时可以省略()

  • 箭头函数函数体只有一行代码时可以省略{},并自动作为返回值被返回

    xml 复制代码
       <script>
          // const fn = function () {
          //   console.log(123)
          // }
          // 1. 箭头函数 基本语法
          // const fn = () => {
          //   console.log(123)
          // }
          // fn()
          // const fn = (x) => {
          //   console.log(x)
          // }
          // fn(1)
          // 2. 只有一个形参的时候,可以省略小括号
          // const fn = x => {
          //   console.log(x)
          // }
          // fn(1)
          // // 3. 只有一行代码的时候,我们可以省略大括号
          // const fn = x => console.log(x)
          // fn(1)
          // 4. 只有一行代码的时候,可以省略return
          // const fn = x => x + x
          // console.log(fn(1))
          // 5. 箭头函数可以直接返回一个对象
          // const fn = (uname) => ({ uname: uname })
          // console.log(fn('刘德华'))
    
        </script>
  • 箭头函数中没有 arguments,只能使用 ...动态获取实参

    xml 复制代码
      <script>
          // 1. 利用箭头函数来求和
          const getSum = (...arr) => {
            let sum = 0
            for (let i = 0; i < arr.length; i++) {
              sum += arr[i]
            }
            return sum
          }
          const result = getSum(2, 3, 4)
          console.log(result) // 9
        </script>

解构赋值

数组解构

  • 变量的顺序对应数组单元值的位置依次进行赋值操作

  • 变量的数量大于单元值数量时,多余的变量将被赋值为 undefined

  • 变量的数量小于单元值数量时,可以通过...获取剩余单元值,但只能置于最末位

    xml 复制代码
      <script>
        // 普通的数组
        let arr = [1, 2, 3]
        // 批量声明变量 a b c 
        // 同时将数组单元值 1 2 3 依次赋值给变量 a b c
        let [a, b, c] = arr
        console.log(a); // 1
        console.log(b); // 2
        console.log(c); // 3
      </script>

对象解构

xml 复制代码
    <script>
      // 普通对象
      const user = {
        name: '小明',
        age: 18
      };
      // 批量声明变量 name age
      // 同时将数组单元值 小明  18 依次赋值给变量 name  age
      const {name, age} = user

      console.log(name) // 小明
      console.log(age) // 18
    </script>

多维解构

xml 复制代码
    <script>
        // 1. 这是后台传递过来的数据
        const msg = {
          "code": 200,
          "msg": "获取新闻列表成功",
          "data": [
            {
              "id": 1,
              "title": "5G商用自己,三大运用商收入下降",
              "count": 58
            },
            {
              "id": 2,
              "title": "国际媒体头条速览",
              "count": 56
            },
            {
              "id": 3,
              "title": "乌克兰和俄罗斯持续冲突",
              "count": 1669
            },

          ]
        }

        // 需求1: 请将以上msg对象  采用对象解构的方式 只选出  data 方面后面使用渲染页面
        // const { data } = msg
        // console.log(data)
        // 需求2: 上面msg是后台传递过来的数据,我们需要把data选出当做参数传递给 函数
        // const { data } = msg
        // msg 虽然很多属性,但是我们利用解构只要 data值
        function render({ data }) {
          // const { data } = arr
          // 我们只要 data 数据
          // 内部处理
          console.log(data)

        }
        render(msg)

        // 需求3, 为了防止msg里面的data名字混淆,要求渲染函数里面的数据名改为 myData
        function render({ data: myData }) {
          // 要求将 获取过来的 data数据 更名为 myData
          // 内部处理
          console.log(myData)

        }
        render(msg)

      </script>

forEach遍历数组(索引号参数可写可不写)

xml 复制代码
    <body>
      <script>
        // forEach 就是遍历  加强版的for循环  适合于遍历数组对象
        const arr = ['red', 'green', 'pink']
        const result = arr.forEach(function (item, index) {
          console.log(item)  // 数组元素 red  green pink
          console.log(index) // 索引号
        })
        // console.log(result)
      </script>
    </body>

filter筛选数组(索引号参数可写可不写)

xml 复制代码
      <script>
        const arr = [10, 20, 30]
        // const newArr = arr.filter(function (item, index) {
        //   // console.log(item)
        //   // console.log(index)
        //   return item >= 20
        // })
        // 返回的符合条件的新数组

        const newArr = arr.filter(item => item >= 20)
        console.log(newArr)
      </script>

对象

构造函数

  • 专门用于创建对象的函数,使用new关键字调用

  • 使用 new 关键字调用函数的行为被称为实例化

  • 实例化构造函数时没有参数时可以省略 ()

  • 构造函数的返回值即为新创建的对象

  • 构造函数内部的 return 返回的值无效!

    xml 复制代码
      <script>
        // 定义函数
        function foo() {
          console.log('通过 new 也能调用函数...');
        }
        // 调用函数
        new foo;
      </script>

实例成员

  • 通过构造函数创建的对象称为实例对象,实例对象中的属性和方法称为实例成员。

  • 构造函数内部 this 实际上就是实例对象,为其动态添加的属性和方法即为实例成员

    xml 复制代码
      <script>
        // 构造函数
        function Person() {
          // 构造函数内部的 this 就是实例对象
          // 实例对象中动态添加属性
          this.name = '小明'
          // 实例对象动态添加方法
          this.sayHi = function () {
            console.log('大家好~')
          }
        }
        // 实例化,p1 是实例对象
        // p1 实际就是 构造函数内部的 this
        const p1 = new Person()
        console.log(p1)
        console.log(p1.name) // 访问实例属性
        p1.sayHi() // 调用实例方法
      </script>

静态成员

  • 静态成员指的是添加到构造函数本身的属性和方法

  • 一般公共特征的属性或方法静态成员设置为静态成员

  • 静态成员方法中的 this 指向构造函数本身

    xml 复制代码
      <script>
        // 构造函数
        function Person(name, age) {
          // 省略实例成员
        }
        // 静态属性
        Person.eyes = 2
        Person.arms = 2
        // 静态方法
        Person.walk = function () {
          console.log('^_^人都会走路...')
          // this 指向 Person
          console.log(this.eyes)
        }
      </script>

内置构造函数

Object

  • 推荐使用字面量方式声明对象,而不是 Object 构造函数
  • Object.assign 静态方法创建新的对象
  • Object.keys 静态方法获取对象中所有属性
  • Object.values 表态方法获取对象中所有属性值

Array

  • forEach:遍历数组
  • filter:过滤数组【筛选数组元素,并生成新数组】
  • map:迭代数组【返回新数组,新数组里面的元素是处理之后的值】
  • reduce:累加器【返回函数累计处理的结果,经常用于求和等】
  • reduce执行过程:1,如果没有起始值,则上一次值是数组的第一个数组元素的值;2,每一次循环,把返回值作为下一次循环的上一次值;3,如果有起始值,则起始值作为上一次值
  • 数组常用方法

string常用方法

原型对象

  • JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象,所以我们也称为原型对象

  • 这个对象可以挂载函数,对象实例化不会多次创建原型上函数,节约内存

  • 我们可以把那些不变的方法,直接定义在 prototype 对象上,这样所有对象的实例就可以共享这些方法。

  • 构造函数和原型对象中的this 都指向 实例化的对象

    xml 复制代码
      <script>
        function Person() {
          // 此处未定义任何方法
        }
    
        // 为构造函数的原型对象添加方法
        Person.prototype.sayHi = function () {
          console.log('Hi~');
        }
    
        // 实例化
        let p1 = new Person();
        p1.sayHi(); // 输出结果为 Hi~
      </script>
  • 构造函数 Person 中定义与原型对象中相同名称的方法,这时实例对象调用则是构造函中的方法 sayHi:

    xml 复制代码
      <script>
        function Person() {
          // 此处定义同名方法 sayHi
          this.sayHi = function () {
            console.log('嗨!');
          }
        }
    
        // 为构造函数的原型对象添加方法
        Person.prototype.sayHi = function () {
          console.log('Hi~');
        }
    
        let p1 = new Person();
        p1.sayHi(); // 输出结果为 嗨!
      </script>
  • 当访问对象的属性或方法时,先在当前实例对象是查找,然后再去原型对象查找,并且原型对象被所有实例共享

constructor属性

  • 每个原型对象里面都有个constructor 属性(constructor 构造函数)
  • 作用:该属性指向该原型对象的构造函数
  • 使用场景:如果有多个对象的方法,我们可以给原型对象采取对象形式赋值.但是这样就会覆盖构造函数原型对象原来的内容,这样修改后的原型对象 constructor 就不再指向当前构造函数了,此时,我们可以在修改后的原型对象中,添加一个 constructor 指向原来的构造函数。

对象原型

  • 对象都会有一个属性 proto 指向构造函数的 prototype 原型对象,之所以我们对象可以使用构造函数 prototype原型对象的属性和方法,就是因为对象有 proto 原型的存在。
  • [[prototype]]和__proto__意义相同
  • 用来表明当前实例对象指向哪个原型对象prototype
  • __proto__对象原型里面也有一个 constructor属性,指向创建该实例对象的构造函数

原型继承

xml 复制代码
    <script>
        // 继续抽取   公共的部分放到原型上
        // const Person1 = {
        //   eyes: 2,
        //   head: 1
        // }
        // const Person2 = {
        //   eyes: 2,
        //   head: 1
        // }
        // 构造函数  new 出来的对象 结构一样,但是对象不一样
        function Person() {
          this.eyes = 2
          this.head = 1
        }
        // console.log(new Person)
        // 女人  构造函数   继承  想要 继承 Person
        function Woman() {

        }
        // Woman 通过原型来继承 Person
        // 父构造函数(父类)   子构造函数(子类)
        // 子类的原型 =  new 父类  
        Woman.prototype = new Person()   // {eyes: 2, head: 1} 
        // 指回原来的构造函数
        Woman.prototype.constructor = Woman

        // 给女人添加一个方法  生孩子
        Woman.prototype.baby = function () {
          console.log('宝贝')
        }
        const red = new Woman()
        console.log(red)
        // console.log(Woman.prototype)
        // 男人 构造函数  继承  想要 继承 Person
        function Man() {

        }
        // 通过 原型继承 Person
        Man.prototype = new Person()
        Man.prototype.constructor = Man
        const pink = new Man()
        console.log(pink)
      </script>

原型链

  • 基于原型对象的继承使得不同构造函数的原型对象关联在一起,并且这种关联的关系是一种链状的结构,我们将原型对象的链状结构关系称为原型链 ① 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。

② 如果没有就查找它的原型(也就是 __proto__指向的 prototype 原型对象)

③ 如果还没有就查找原型对象的原型(Object的原型对象)

④ 依此类推一直找到 Object 为止(null)

⑤ __proto__对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线

⑥ 可以使用 instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

JSON

  • JSON是一个字符串
  • JSON.parse(str1)--将json字符串转换为对象
  • JSON.stringify(obj)--将对象转换为字符串

深浅拷贝

  • 浅拷贝:拷贝基础类型数据没有问题,但是拷贝对象会彼此影响(只能拷贝对象地址,指向同一个对象,一改全改)

  • 深拷贝方法:递归拷贝;JSON序列化;lodash工具

  • JSON深拷贝:

    javascript 复制代码
      let obj2 = JSON.parse(JSON.stringify(obj1))

改变this指向

call

  • call 方法能够在调用函数的同时指定 this 的值

  • 使用 call 方法调用函数时,第1个参数为 this 指定的值

  • call 方法的其余参数会依次自动传入函数做为函数的参数

    xml 复制代码
      <script>
        // 普通函数
        function sayHi() {
          console.log(this);
        }
    
        let user = {
          name: '小明',
          age: 18
        }
    
        let student = {
          name: '小红',
          age: 16
        }
    
        // 调用函数并指定 this 的值
        sayHi.call(user); // this 值为 user
        sayHi.call(student); // this 值为 student
    
        // 求和函数
        function counter(x, y) {
          return x + y;
        }
    
        // 调用 counter 函数,并传入参数
        let result = counter.call(null, 5, 10);
        console.log(result);
      </script>

apply

  • apply 方法能够在调用函数的同时指定 this 的值

  • 使用 apply 方法调用函数时,第1个参数为 this 指定的值

  • apply 方法第2个参数为数组,数组的单元值依次自动传入函数做为函数的参数

    xml 复制代码
      <script>
        // 普通函数
        function sayHi() {
          console.log(this)
        }
    
        let user = {
          name: '小明',
          age: 18
        }
    
        let student = {
          name: '小红',
          age: 16
        }
    
        // 调用函数并指定 this 的值
        sayHi.apply(user) // this 值为 user
        sayHi.apply(student) // this 值为 student
    
        // 求和函数
        function counter(x, y) {
          return x + y
        }
        // 调用 counter 函数,并传入参数
        let result = counter.apply(null, [5, 10])
        console.log(result)
      </script>

bind

  • bind 方法并不会调用函数,而是创建一个指定了 this 值的新函数

    xml 复制代码
      <script>
       // 普通函数
       function sayHi() {
         console.log(this)
       }
       let user = {
         name: '小明',
         age: 18
       }
       // 调用 bind 指定 this 的值
       let sayHello = sayHi.bind(user);
       // 调用使用 bind 创建的新函数
       sayHello()
     </script>
相关推荐
neter.asia4 分钟前
vue中如何关闭eslint检测?
前端·javascript·vue.js
~甲壳虫5 分钟前
说说webpack中常见的Plugin?解决了什么问题?
前端·webpack·node.js
光影少年24 分钟前
vue2与vue3的全局通信插件,如何实现自定义的插件
前端·javascript·vue.js
As977_25 分钟前
前端学习Day12 CSS盒子的定位(相对定位篇“附练习”)
前端·css·学习
susu108301891127 分钟前
vue3 css的样式如果background没有,如何覆盖有background的样式
前端·css
Ocean☾29 分钟前
前端基础-html-注册界面
前端·算法·html
Dragon Wu31 分钟前
前端 Canvas 绘画 总结
前端
CodeToGym36 分钟前
Webpack性能优化指南:从构建到部署的全方位策略
前端·webpack·性能优化
~甲壳虫37 分钟前
说说webpack中常见的Loader?解决了什么问题?
前端·webpack·node.js
~甲壳虫41 分钟前
说说webpack proxy工作原理?为什么能解决跨域
前端·webpack·node.js