步入放羊之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>
相关推荐
桂月二二43 分钟前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
hunter2062062 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb2 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角2 小时前
CSS 颜色
前端·css
浪浪山小白兔3 小时前
HTML5 新表单属性详解
前端·html·html5
lee5764 小时前
npm run dev 时直接打开Chrome浏览器
前端·chrome·npm
2401_897579654 小时前
AI赋能Flutter开发:ScriptEcho助你高效构建跨端应用
前端·人工智能·flutter
limit for me4 小时前
react上增加错误边界 当存在错误时 不会显示白屏
前端·react.js·前端框架
浏览器爱好者4 小时前
如何构建一个简单的React应用?
前端·react.js·前端框架
qq_392794484 小时前
前端缓存策略:强缓存与协商缓存深度剖析
前端·缓存