JS - 高级

JS高级

函数

  • 函数声明

    • 函数声明的时候,函数体不会执行,只要函数被调用的时候才会执行

    • 函数一般用来干一件事情,函数名称一般使用动词

      function 函数名(){
      //函数体
      }

  • 函数表达式

    var fn =function(){
    //函数体
    }

  • 函数的调用

    • 函数体只有在调用的时候才会执行,调用需要()进行调用,可以调用多次

      函数名();
      // 声明函数
      function sayHi() {
      console.log("吃了没?");
      }
      // 调用函数
      sayHi();

  • 函数的参数

    • 形参:声明函数时,给函数设置参数,这个参数没有具体的值,只起到占位作用。
    • 实参:如果函数声明设置了形参,调用时就需要传入对应的参数,这个传入的参数叫实参
  • 函数的返回值

    • 当函数执行完毕时,我们期望函数给我们一些反馈(比如计算的结果返回进行后续的运算)这就是返回值,通过return返回一个返回值。
    • 函数的调用结果就是返回值,可以直接对函数调用结果进行操作。
    • 返回值详解
      • 函数没有 return 返回 undefined
      • 函数 有return 跟在return后面的值就是函数的返回值
      • 函数有return后面没有任何值,返回 undefined
      • 函数使用return语句,这个函数就会在执行完return之后停止并立即退出,return后面的所有代码不再执行。
  • 匿名函数

    • 没有名字的函数
    • 将匿名函数赋值给一个变量,通过变量进行调用
    • 或者匿名函数自调用
  • 自调用函数

    • 匿名函数不能直接通过调用来执行,因此可以通过匿名函数自调用的方式来执行

      (function () {
      alert(123);
      })();

  • 函数是一种数据类型

    • 函数作为参数

      • 函数可以作为另一个函数的参数,在另一个函数中调用
    • 函数作为返回值

      • 函数可以作为返回值从函数内部返回

      function fn(b) {
      var a = 10;
      return function () {
      alert(a+b);
      }
      }
      fn(15)();

new关键字

  1. new在执行时会做四件事情:
  2. new会在内存中创建一个新的空对象
  3. new 会让this指向这个新的对象
  4. 执行构造函数 目的:给这个新对象加属性和方法
  5. new会返回这个新对象

this 详解

对象的使用

  • 遍历对象的属性

  • for in 可以遍历对象的成员

    for (var key in obj){
    console.log(key)//-->属性名
    console.log(obj[key])//--对应的属性值
    }

  • 删除属性

    delete 对象.属性名

构造函数

对象的属性和方法叫做对象的成员

  1. 函数内部创建的属性和方法叫做实例对象/对象成员
  2. 跟对象相关的成员,将来使用对象的方式调用
  3. 静态成员:直接给构造函数增加成员
  4. 静态成员不能使用对象的方式调用,使用构造函数调用(Hero.成员)
  5. 实例成员与对象有关,静态成员与对象无关

原型对象

  1. 每个构造函数都有一个属性,就是原型对象prototype
  2. 构造函数通过原型对象增加的方法和属性,构造函数创建的所有对象都可以访问,而且在在内存中只有一份
  3. 对象通过打点的方式增加属性,而 构造函数.prototype 也是一个对象,也可以通过打点的方式增加方法,而且构造函数创建的所有对象都可以增加了这个方法(语法:构造函数.prototype.方法=function(){})
  4. 使用原型对象增加方法和在构造函数内增加方法的区别:当调用对象的属性或方法,先去找对象的属性或方法,如果对象没有该属性/方法,此时去调用原型中的属性或方法
  5. 对象.proto = 构造函数.prototype (通过构造函数(Hero)创建对象(hero1))
  6. 只要有对象,都有proto这个属性,在原型对象中有个属性叫constructor,这个属性叫构造函数,可以打印出这个构造函数,访问方式,对象.constructor,constructor记录了创建给对象的构造函数,可以判断这个对象是由哪个构造函数创建的

构造函数 原型对象 实例/对象 之间的关系

  • 构造函数创建对象
    构造函数的原型属性prototype 构造函数 拥有 原型对象
  1. 对象的属性proto 指向 构造函数的原型对象

原型链

  1. 原型链的顶端是null
  2. s1对象的原型对象的原型对象就是Object构造函数的原型对象
    s1.proto.proto===Object.prototype
  3. 读取属性时,先在对象本身查找,找不到就去原型链里找
  4. 设置属性时,不会搜索原型链,而是给这个对象新增一个属性并赋值
  5. 当我们改变构造函数的prototype时,需要重新设置constructor属性
  6. 先设置原型属性,在创建对象,才可以访问原型对象中的成员

原型对象的应用

数组或String中的prototype是不可以重新赋值修改的

继承

面向对象三大特征: 封装 继承 多态(抽象)

继承:类型和类型之间的关系

继承的目的::把子类型中共同的成员提取到父类型中,代码重用

原型继承:无法设置构造函数的参数

借用构造函数(造函数的属性继承)

  1. call()改变函数的this,直接调用函数,call的第一个参数是要改变的指向对象
  2. 在函数内部,通过 call(借用的函数,参数),借用了构造函数继承了属性成员
  3. 借用构造函数的方法只有在构造函数内方法可以继承,通过原型对象增加的方法不能继承

组合继承

  1. 组合继承:借用构造函数+ 原型继承
  2. 借用构造函数(在函数内部使用call) + 原型继承(子类型.protopyte=父类型.prototype)
  3. 借用构造函数,让teacher继承person里的属性,设置teacher的原型对象,继承person里的方法(teache.prototypr=new Person();),

函数的进阶

  • 函数声明和函数表达式的区别:函数表达式的变量会提升,结果为undifined,函数声明不会提升

  • if语句内,函数不会提升

  • 函数定义方式:函数也是对象,可以传参,有属性和方法

    var fn=new Function('a','b','console.log(a+b));
    fn(1,2);

函数的调用方式

  • 普通函数调用:this指向window,谁调用这个方法,this指向谁

    function fn(){
    console.log(this)
    }
    fn();

  • 方法调用:this指向调用该方法的对象

    var obj={
    fn:function(){
    console.log(this)
    }
    }
    obj.fn();

  • 作为构造函数调用【call ()】:this指向由这个构造函数创建的对象

  • 作为事件的处理函数调用:this指向触发该事件的对象

    btn.onclick=function(){
    console.log(this)
    }

  • 作为定时器的参数:this指向window

    setInterval(function(){
    console.log(this)
    },1000)

==函数内部的this是由函数调用的时候确定其指向==

call 、apply 和bind()改变函数中的this

function fn(x,y){
    console.log(this);
    console.log(x+y);
}
fn(5,6) //this-->window

var obj={
    name:'zs'
}
fn.call(obj,5,6); //-->obj对象和11
fn.apply(obj,[1,8]);//fn内需要几个参数,数组中传几个参数
//-->obj和9

//bind不会调用函数,要想调用需要用一个变量接收bind的返回值
var f=fn.bind(obj,2,2);
f();//不用传递参数直接调用
  • call方法:
  1. 调用函数,改变函数中的this
  2. 第一参数,设置函数内部this的指向,其他参数,对应函数的参数
  3. 函数的返回值,call的返回值就是fn函数的返回值
  • apply方法:
  1. 调用函数,改变函数中的this
  2. 第一个参数: 设置函数内部this的指向,第二个参数是数组
  3. 函数的返回值,call的返回值就是fn函数的返回值
  • bind方法:
  1. 改变函数中的this,但不会调用函数,而是把函数复制一份
  2. 第一参数,设置函数内部this的指向,其他参数,对应函数的参数
  3. 函数的返回值,call的返回值就是fn函数的返回值

call的应用

Array.prototype.getSum=function(){
    this指谁?
}
var arr=[1,2,3];
arr.getSum();//通过数组调用,this指向这个数组
arr.push(); //数组本身提供了,push、splice方法
arr.splice(); //删除数组元素  splice(从那一项删除,删除几项)

伪数组

var Obj={
    0:100,
    1:10,
    2,:11,
    3:20,
    length:4
};

给这个数组追加属性:

方法一:

obj['4']=12; //(数字不能作为变量和属性开头,所以用obj['4'])
obj.length++;

方法二:

数组的push方法(让伪数组借用数组的方式)

Array.prototype.push.call(obj,30);
//给Array的原型对象push一个对象,
//并且通过call改变this指向,
//指向obj,就给obj追加了数组

所有的对象都有toString()这个方法

  • object.toString()--->Object(代表是一个对象) object(这个对象的类型)
  • arr.tostring()-->数组里的值 1,2,3
  • Object.prototype.toString.call(arr) ---> object Array (数组对象的类型)

apply的应用

语法:fn.apply(,[])

常用于把数组展开,传递给前面的方法

var arr = [5,8,10,2]
console.log(Math.max(arr))//--.NAN Math.max不能求数组中的最大值
<!--可以把数组中的每一项展开,传给max,返回最大值-->
Math.max.apply(null,arr)
<!--max中的this指向math,所以不用改变指向-->
Math.max.apply(Math,arr)

bind的应用

bind和apply、call的区别在于bind不会去调用方法,而是去复制方法

  • 应用一

    var obj = {
    name:'zs',
    fun:function(){
    setInterval(function(){
    console.log(this.name)
    }.bind(this),1000);
    }
    }
    obj.fun()

  • 应用二

    btn.onclick=function(){


    }.bind(obj)

小结

  • call 和 apply 特性一样
    • 都是用来调用函数,而且是立即调用
    • 但是可以在调用函数的同时,通过第一个参数指定函数内部 this 的指向
    • call 调用的时候,参数必须以参数列表的形式进行传递,也就是以逗号分隔的方式依次传递即可
    • apply 调用的时候,参数必须是一个数组,然后在执行的时候,会将数组内部的元素一个一个拿出来,与形参一一对应进行传递
    • 如果第一个参数指定了 null 或者 undefined 则内部 this 指向 window
  • bind
    • 可以用来指定内部 this 的指向,然后生成一个改变了 this 指向的新的函数
    • 它和 call、apply 最大的区别是:bind 不会调用
    • bind 支持传递参数,它的传参方式比较特殊,一共有两个位置可以传递
        1. 在 bind 的同时,以参数列表的形式进行传递
        1. 在调用的时候,以参数列表的形式进行传递
      • 那到底以谁 bind 的时候传递的参数为准呢还是以调用的时候传递的参数为准
      • 两者合并:bind 的时候传递的参数和调用的时候传递的参数会合并到一起,传递到函数内部

函数中的其他成员

  • arguments
    • 伪数组,获取到的是函数的实参,实参集合
  • caller
    • 函数的调用者,在全局范围调用的时候caller是null
  • name
    • 函数的名称,字符串类型
  • length
    • 函数的形参个数

arguments应用

//当函数的参数个数不固定的时候
//在函数内部,可以通过arguments获取到实际传过来的参数
function max(){
    var max = arguments[0];//假设第一个参数为最大值
    for(var i=0,i<arguments.length;i++){
        if(max<arguments[i]){//如果最大值小于遍历的这个参数
            max=arguments[i];//那么让这个参数为最大值
        }
    }
}
console.log(max(2,7,9,4)); //-->9
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341

推荐阅读更多精彩内容