JS 高级

继承

构造函数继承

  <script>// 构造函数继承// 定义的Person类function Person(name, age) {this.name = name;this.age = age;}// 定义的Student类function Student(name, age) {// 继承// 借用构造函数继承属性成员Person.call(this, name, age);}var stu = new Student("老王", 30);console.log(stu.name); // 老王console.log(stu.age); // 30</script>

拷贝继承(for - in)

  <script>// copy 继承// 定义的Person类function Person(name, age) {this.name = name;this.age = age;}// 用 prototype 给 Person类 添加新的属性方法Person.prototype.sayHi = function () {console.log(`${this.name}:'Hi'`);};// 定义的Student类function Student(name, age) {// 继承属性Person.call(this, name, age);}// copy 继承,继承原型的属性for (var key in Person.prototype) {Student.prototype[key] = Person.prototype[key];}var stu = new Student("张三", 20);console.log(stu.name); // 张三console.log(stu.age); // 20stu.sayHi();</script>

另一种继承方式:原型继承

  <script>// 定义的Person类function Person(name, age) {this.name = name;this.age = age;}// 用 prototype 给 Person类 添加新的属性方法Person.prototype.sayHi = function () {console.log(`${this.name}:'Hi'`);};// 定义的Student类function Student(name, age) {// 继承属性 Person.call(this, name, age);}// 将 Person 对象赋值给 Student 的原型// Student.prototype = new Person(); // new Person() PersonStudent.prototype = Person.prototype; // Person.prototype Objectvar stu = new Student("张三", 20);console.log(stu);stu.sayHi();</script>

函数

函数进阶 - 函数的定义方式

  • 函数声明

    •     // 函数的定义方式:声明式function foo() {}
      
  • 函数表达式

    •     // 字面量方式 :表达式var foo = function () {};
      
  • 函数声明与函数表达式的区别

    • 函数声明必须要有名字

    • 函数声明会函数提升,在预解析创建就已创建,声明前后都可以调用

    • 函数表达式类似于变量赋值

    • 函数表达式可以没有名字,例如匿名函数

    • 函数表达式没有变量提升,在执行阶段创建,必须在表达式执行之后才可以调用

        <script>// 函数的定义方式:声明式 变量提升function foo() {}// 字面量方式 :表达式// 没有变量提升// foo() 会报错var foo = function () {};</script>
      

函数进阶 - 函数的调用方式

  • 普通函数
  • 构造函数
  • 对象方法
  <script>// 普通函数function foo() {}foo();// 构造函数function F() {}var a = new F();// 对象的函数var c = {sayHi: function () {},};c.sayHi();</script>

函数进阶 - 函数内 this 指向的不同场景

  • 函数的调用方式决定了 “this” 指向的不同:

    调用方式 非严格模式 备注
    普通函数调用 window 严格模式下是 undefined
    构造函数调用 实例对象 原型方法中 this 也是实例对象
    对象方法调用 该方法所属对象 紧挨着的对象
    事件绑定方法 绑定事件对象
    定时器函数 window
  <body><button id="btn">按钮</button></body><script>// 普通函数function foo() {console.log(this); // window}foo();// 构造函数function Person() {console.log(this); // 指向实例对象 Person}var p = new Person();var obj = {name: "张三",age: 30,sayHi: function () {console.log(this); // obj 张三},grilFriend: {name: "小红",talk: function () {console.log(this); // grilFriend 小红},},};// console.log(obj);obj.sayHi();obj.grilFriend.talk();document.getElementById("btn").onclick = function () {console.log(this); // <button id="btn">按钮</button>};// 定时器函数setTimeout(function () {console.log(this); // window}, 2000);</script>

函数进阶 - call、apply、bind

  • 了解了函数 this 指向的不同场景之后
  • 我们知道有些情况下我们为了使用某种特定环境的 this 引用,这时候我们就需要采用一些特殊手段来处理了,例如我们经常在定时器外部备份 this 引用,然后在定时器函数内部使用外部 this 的引用
  • 然而实际上对于这种做法我们的 JavaScript 为我们专门提供了一些函数方法用来帮我们更优雅的处理函数内部 this 指向问题。
  <script>// 更改 this 指向var obj = {name: "张三",sayHi: function () {console.log(this); // objvar _this = this;setTimeout(function () {console.log(this); // windowconsole.log(name); // ''console.log(this.name); // ''console.log(_this.name); // 张三}, 2000);},};obj.sayHi();</script>

call

  • call()方法调用一个函数,其具有一个指定的 this 值和分别提供的参数(参数的列表)。
  • 注意:该方法的作用和 apply() 方法类似,只有一个区别,就是 call() 方法接受的是若干个参数的列表,而 apply()方法接受的是一个包含多个参数的数组。
  • 语法:fun.call(thisArg,arg1,arg2)
  • 参数:
    • thisArg

      • 在 fun 函数运行时指定的 this 值
      • 如果指定了 null 或者 undefined 则内部 this 指向 window
    • arg1,arg2,...

      • 指定的参数列表
  <script>var obj = {name: "admin",};function foo(a, b) {console.log(a + b); // 30console.log(this.name); // admin this指向了obj}foo.call(obj, 10, 20);</script>

apply

  • apply()方法调用一个函数,其具有一个指定的this值,以及作为一个数组(或类似数组的对象)提供的参数

  • 注意:该方法的作用和call()方法类型,只有一个区别,就是call()方法接受的是若干个参数的列表,而apply()方法接受的是一个包含多个参数的数组

  • 语法:fun.apply(thisArg,[argsArray])

  • 参数:

    • thisArg
    • argsArray
  • apply()call()非常相似,不同之处在于提供参数的方式

  • apply()使用参数数组而不是一组参数列表

  • 例如:fun.apply(this,['eat','bananas'])

      <script>var obj = {name: "admin",};function foo(a, b) {console.log(a + b); // 30console.log(this.name); // admin this指向了obj}foo.apply(obj, [10, 20]);// call 和 apply 很相似,只是在传递参数的时候一个是列表,一个是数组</script>
    

bind

  • bind()函数会创建一个新函数(称为绑定函数),新函数与被调函数(绑定函数的目标函数)具有相同的函数体

  • 当目标函数被调用时this值绑定到bind()的第一个参数,该参数不能被重新。绑定函数被调用时,bind()也接受预设的参数提供给原函数

  • 一个绑定函数也能使用 new 操作符创建对象:这种行为就像把原函数当成构造器。提供的this值被忽略,同时调用时的参数被提供给模拟函数

  • 语法:fun.bind(thisArg,arg1,arg2)()

  • 参数:

    • thisAry

      • 当绑定函数被调用时,该参数会作为原函数运行时的this指向。当使用 new 操作符调用绑定函数时,该参数无效
    • arg1,arg2,...
      • 当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法
      <script>var obj = {name: "admin",};function foo(a, b, c, d) {console.log(a + b); // 30console.log(this.name); // admin this指向了objconsole.log(c, d); // 30 40}// 最后一个括号表示调用// 会将两个括号中的参数进行合并 全部传递foo.bind(obj, 10, 20)(30, 40);</script>
    

小结:

  • call 和 apply 特性一样

    • 都是用来调用函数,而且是立即调用
    • 但是可以在调用函数的同时,通过第一个参数指定函数内部this的指向
    • call 调用的时候,参数必须是以参数列表的形式进行传递,也就是逗号分割的方式依次传递即可
    • apply 调用的时候,参数必须是一个数组,然后在执行的时候,会将数组内部的元素一个一个拿出来,与形参一一对应进行传递
    • 如果一个参数指定了 null 或者 undefined 则内部 this 指向 window
  • bind

    • 可以用来指定内部 this 的指向,然后生成一个改变了 this 指向的新的函数
    • 它和 call、apply 最大的区别是:bind 不会调用
    • bind 支持传递参数,它的传递方式比较特殊,一个有两个位置可以传递
      • 在 bind 的同时,以参数列表的形式进行传递
      • 在调用的时候,以参数列表的形式进行传递
    • bind 传递参数的时候以传递的参数为准还是以调用的时候传递的参数为准
      • bind 的时候传递的参数和调用的时候的参数会合并到一起,传递到函数内部

函数的其他成员

  • arguments

    • 实参集合
  • length
    • 形参的个数
  • name
    • 函数的名称
  <script>function a() {console.log(arguments); // 参数列表 10 20 30 40 是一个伪数组}a(10, 20, 30, 40);// 函数形参的个数console.log(a.length); // 4console.log(a.name); // avar foo = "FOO";var obj = {[foo]: function () {console.log("123456");},};obj[foo]();console.log(obj[foo].name); // FOO</script>

高级函数

  • 函数可以作为参数
  • 函数可以作为返回值
  <script>// 高阶函数// 第一种:参数是一个函数 map filter reduce forEachvar a = [1, 2, 3];var b = a.map(function (item, index, arr) {return item * 2;});console.log(b);var c = a.filter(function (item, index, arr) {return item == 3;});console.log(c);var d = a.reduce(function (pre, item, index, arr) {return (pre += item);}, 0);console.log(d);a.forEach(function (item, index, arr) {console.log(item);});// 第二种高阶函数:返回值是一个函数function foo() {return function () {console.log(10);};}// var f = foo();// f();foo()();</script>

函数闭包

  • 一个函数对其周围状态的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)
  • 也就是说,闭包让你可以在一个内存函数中访问到其外层函数的作用域。在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来
  <script>function foo() {var counter = 10;return {printCounter: function () {console.log(counter);},};}// 调用函数 返回一个对象var obj = foo();// 对象调方法obj.printCounter();// 链式调用foo().printCounter();</script>

作用域

  • 全局作用域
  • 函数作用域
  • 没有块级作用域
  <script>// 代码块{var a = 10; // 全局作用域}console.log(a); // 10// function foo() {//   console.log(a);// }// foo();(function foo() {console.log(a); // 10})();</script>

作用域链

  • 内层作用域可以访问外层作用域,反之不行
  <script>var a = 10;function fn() {var b = 20;function fn1() {var c = 30;console.log(a + b + c); // 60}function fn2() {var d = 40;console.log(c + d); // 报错}fn1();fn2();}fn();</script>

JS 高级(继承、函数)相关推荐

  1. JS高级——纯函数、柯里化(手写自动柯里化函数)、组合函数(手写自动组合函数)

    一.理解JavaScript纯函数 函数式编程中有一个非常重要的概念叫纯函数,JavaScript符合函数式编程的范式,所以也有纯函数的概念: 在react开发中纯函数是被多次提及的: 比如react ...

  2. 前端与移动开发----JS高级----面向对象编程,类与实例对象,继承,严格模式,模板字符串,class封装tab栏

    JS高级01 回顾上阶段 Javascript组成 ECMAScript: 基础语法 (变量, 表达式, 循环, 判断, 函数, 对象等) DOM: document 操作标签(获取, 增加, 插入, ...

  3. Node.js: 如何继承 events 自定义事件及触发函数

    events 是node.js的核心api ,几乎大部分node.js 的api都继承 events 类(javascript中没有类,也不存在继承,确切说是模拟类和继承,点击查看) 比如我们常见的 ...

  4. 05【JS 高级】-【PC端网页特效】元素偏移量 offset 系列, 元素可视区 client 系列, 元素滚动 scroll 系列, 动画函数封装, 常见网页特效案例

    04[JS 高级]-[PC端网页特效] 学习内容: 元素偏移量 offset 系列, 元素可视区 client 系列, 元素滚动 scroll 系列, 动画函数封装, 常见网页特效案例 1. 元素偏移 ...

  5. js高级第一章--变量提升,函数提升

    js高级第一章–变量提升,函数提升 文章目录 前言 一.什么是js里的提升? 二.js变量提升 三.js函数提升 四.特殊情况 总结 前言 在js中,最基本的声明方式有三种,即:var,let,con ...

  6. JS面向对象——原型式继承函数、寄生式继承函数、寄生组合式继承

    一.原型式继承函数 回顾一下JavaScript想实现继承的目的:重复利用另外一个对象的属性和方法. 最终的目的:student对象的原型指向了person对象: 二.寄生式继承函数 寄生式(Para ...

  7. 【JavaScript总结】JavaScript语法基础:JS高级语法

    作用域链: 1.JS中只有函数能够限定作用域的范围: 2.变量处理在制定的函数范围内,还有一个特殊的作用域,就是没有用var 声明的全局作用域 3.js中的作用域链是为了清晰的表示出所有变量的作用范围 ...

  8. 前端知识点总结——JS高级(持续更新中)

    前端知识点总结--JS高级(持续更新中) 1.字符串 什么是: 连续存储多个字符的字符数组 相同: 1. 下标 2. .length 3. 遍历 4. 选取: slice(starti[, endi] ...

  9. 面试官问:JS的继承

    原文作者若川,掘金链接:https://juejin.im/post/5c433e216fb9a049c15f841b 写于2019年2月20日,现在发到公众号声明原创,之前被<前端大全> ...

最新文章

  1. 跨越企业的“中等收入陷阱”
  2. 旷视科技 Face++ 全资收购艾瑞思机器人 正式进军机器人业务
  3. Serverless 初体验:快速开发与部署一个Hello World(Java版)
  4. Serious Python
  5. AtCoder AGC004F Namori (图论)
  6. SpringMVC的返回值和参数类型
  7. sax解析xml案例一
  8. 极客大学架构师训练营 加密技术 高可用系统的度量 高可用系统的架构 高可用系统的运维 第22课 听课总结
  9. SIP - pjsip Linux Windows 编译安装
  10. 2016版excel_巧用这些Excel大神技巧,半小时做完一天工作,办公室女神惊呆了!...
  11. [4G5G专题-101]:部署 - LTE FDD与LTE TDD技术差异比较详解
  12. HDU 6441 Find Integer 费马大定理
  13. 从来也科技首次入选Gartner RPA魔力象限报告,看国产RPA未来发展
  14. 移动开发唱衰,iOS开发者如何涅槃重生?
  15. vmware设置虚拟机静态ip
  16. 【毛坦厂复读生心中所想】—— 我在大学挺好的【内附学习资源和路线】
  17. win10计算机联接多个网络,如何设置win10电脑连接两个显示器?
  18. AGV移动机器人PID运动控制
  19. 自动测试如何选择自动化测试框架_机器擅长回归测试,人类善于寻找Bug _Pekka Klärck
  20. SuperMap Objects组件式开发

热门文章

  1. 利用R语言通过holtwinters模型进行预测
  2. 2021年茶艺师(初级)考试试卷及茶艺师(初级)考试申请表
  3. (轉貼) 接手一年亏损270亿西门子手机厂 明基不玩了 (News)
  4. muduo网络库学习(1)
  5. ros下创建节点后运行总是出现[rospack] Error: package '***' not found
  6. 蒸螃蟹冷水蒸还是开水,冷水上锅蒸的螃蟹不掉腿
  7. New Bing相关设置与解除聊天次数限制
  8. 公众号认证提示法定代表人身份证号码,工商数据未更新怎么办?
  9. PCL点云库安装及学习(2021.7.28)
  10. postgresql 高可用 patroni + etcd 之二 patroni