Javascript高级

基础知识深入

1、关于作用域的小问题

 var a={age:15}

        function fun(obj){

            obj={age:13}

        }

      fun(a)

      console.log(a,a.age)//{age: 15}  15

var b=3

        function fun2(b){

            b=b+1

        }

      fun2(b)

      console.log(b) //3

解释:其实形参相当于是赋值,也就是相当于obj=a;这个时候,obj指向的是{age:15},然后在函数内部使得obj指向的是{age:13},然后函数结束以后局部变量被销毁。所以a的指向一直都没有改变,所以a依然是指向{age:15}

 

2、对象---什么时候必须使用['属性名']的方式?

1)属性名包含特殊字 符:- 空格

2)属性名不确定,下面属性名是myAge 赋值给一个变量

var propName="myAge"

var value=18

p.propName=value //不能用

p[propName]=value //可以

 

3、函数

①call的其他理解

var obj={}

funtion test(){

this.name="sjw"

this.age=18// 是改变this指向,也是给obj添加属性

this.setAge=function(){

this.age=22

}

}

这个时候不可以obj.name因为obj是空对象

test.call(obj)//改变了this的指向

console.log(obj.name)//sjw

obj.setAge()

 console.log(obj.age)//22

并且console.log(obj)

{name:"sjw",age:18} 相当于是改变了obj的内容

除了理解为改变this的指向,其他理解为:让函数成为指定的任意对象的方法进行调用

②回调函数

1)什么函数才是回调函数:

1>你定义的

2>你没有调

3>执行了(在某个条件满足时)

2)一般的回调函数

1>定时器回调函数

2>dom事件回调函数

3>ajax请求回调函数

4>生命周期回调函数

③IIFE(立即执行函数表达式)

作用:隐藏实现,不会污染外部(全局)的命名空间

;(function (){

        var a=3

            console.log(a+3)//6

         })()

         var a=4

         console.log(a) //4

-----------------------------------------------------------------------------

;(function (){

            var b=1

            function test(){

                console.log(++b)

            }

            window.xx=function(){

                return{

                    test:test //相当于向外暴露一个函数test

                } 

            }

         })()

         obj=xx()

         obj.test() //2

         xx().test() //3

④函数中的this

1)this是什么?

任何函数本质上都是通过对象调用的,如果没有直接指定就是window

所有函数内部都有一个变量this

2)如何确定this的值

* test() //window

* p.test() //p

* new test() //新创建的对象

* p.call(obj) //obj

tips:小括号开头前一句和中方括号开头的前一句要加; 其他自由

 

JS高级

1、原型和原型链

1)函数的prototype

* 每个函数都有一个prototype属性,他默认指向一个object空对象(原型对象)

* 原型对象中有一个属性constructor,它指向函数对象

 

2)给原型对象添加属性(一般为方法)

* 作用:函数中所有实例对象自动拥有原型中的属性(方法)

 

3)显式原型和隐式原型

* 每个函数function都有一个显式原型propotype

* 每个实例对象都有一个隐式原型__proto__(都保存着地址值)

var fn=new Fn() //相当于this.__propo=Fn.propotype

 

此外,Fn.prototype.constructor=Fn 也就是空object里面还有一个属性,指向函数对象

4)原型链

* 访问一个对象属性时

* 现在自己身上找

* 没有在自己的原型对象上找

* 顺着__proto__原型链找 找到返回 找到Object上还没有的话,返回undefined

 

5)补充内容:

* 函数的显式原型指向对象默认是空Object实例对象(但Object不满足)

* 所有函数都是Function的实例(包括Function)

Function.__proto__===Function.prototype

* Objetc对象的原型对象是原型链尽头

Object.prototype.__proto__=null

 

6)原型链_属性设置

* 设置对象的属性值时:不查找原型链,若当前对象中没有此属性,直接添加此属性并设置

function fn(){

}

fn.prototype.a="xxx"

var fn1=new fn( )

console.log(fn1.a) // xxx

var fn2=new fn( )

fn2.a="yyy"

console.log(fn1.a) // xxx 没改变因为fn2加的在自己的对象上 而不在原型上

* 方法一般定义在原型上,属性一般定义在对象本身上

 

7)关于instanceof

函数Foo的原型对象又是空的Object的实例对象,因此也有__proto__指向Object( )函数的原型对象(实例对象的隐式原型等于构造函数的显式原型)

2、执行上下文和执行上下文栈

1)变量声明提升和函数提升

var a=3;

function fn( ){

console.log(a) // undefined

var a=4;

}

相当于:

var a=3;

function fn( ){

var a;

console.log(a) // undefined

a=4;

}

注意:没有赋值,只是把声明提升

-----------------------------------------------------------------------------------------------------------------

fn() //可以调用 函数提升

function fn( ){

var a;

console.log(a) // undefined

a=4;

}

注意:先执行变量提升,然后再执行函数提升

2)执行上下文栈....

 

3、作用域和作用域链

1)分类

* 全局作用域

* 局部作用域

* es6有了块作用域

2)作用:隔离变量,不同作用域下同名的变量不会冲突

3)n+1原则:n是你定义的函数,1是全局作用域

 

fn(10)

4)作用域链

*先在自己的作用域中找,没有的话在上一级的作用域中找

var a=1

function fn1( ){

var b=2

function fn2( ){

var c=3

console.log(c)

console.log(b)

console.log(a)

console.log(d)

}

fn2( )

}

fn1( ) //执行后:3 2 1 报错

 

答案:10 原因是作用域本身已经形成了,所以你虽然调用是嵌套的 但是实际的作用域还是在fn()n那 因此x还是去全局作用域寻找

 

4、闭包

1)如何产生闭包:

* 当一个嵌套的子函数引用了嵌套的外部(父)函数的变量(函数)时,就产生了闭包。

 

2)闭包到底是什么?

* 闭包是嵌套的内部函数

* 包含被引用变量(函数)的对象

function fn1(){

            var a=2

            function fn2(){

                console.log(a)

            }

            return fn2

        }

        fn1()

 

3)产生闭包的条件?

* 函数嵌套

* 内部函数引用外部函数的数据(变量/函数)

* 产生几个闭包由调用了几次外部函数决定

function fn1(){

            var a=2

            function fn2(){

                a++

                console.log(a)

            }

            return fn2

 

        }

        var f=fn1()

        f() //3

        f() //4

 

4)闭包的作用

* 使用函数内部的变量在函数执行完后,依然存活在内存中(延长局部变量的生命)

* 让函数外部可以操作(读写)到函数内部的数据(变量/函数)

注:* 函数执行完后,函数内部声明的局部变量一般是不存在,存在于闭包之中的才会存在

* 在函数外部能直接访问内部的局部变量吗?不能 但可以通过闭包让外操作他问

 

5)闭包的应用

* 具有特定功能的js文件

* 将所有的数据和功能都封装在一个函数中(私有的)

* 向外只暴露一个包含n个方法的对象或函数

* 模块的使用者,只需要通过模块暴露的对象调用方法来实现对应的功能

以下示例两种封装的js方式,使用到了闭包

function test(){

            var msg="sjw"

            //操作数据的函数

            function dosomething(){

                console.log("dosomething"+msg.toLocaleUpperCase())

            }

            function doanything(){

                console.log("doanything"+msg.toLocaleUpperCase())

            }

 

            return message1={

                dosomething:dosomething,

                doanything:doanything

            }

        }

        var message1=test()

        message1.dosomething() //dosomethingSJW

        message1.dosomething() //doanythingSJW

    -------------------------------------------------------------------------

        ;(function(window){

            //私有的数据

            var msg="sjw"

            //操作数据的函数

            function dosomething(){

                console.log("dosomething"+msg.toLocaleUpperCase())

            }

            function doanything(){

                console.log("doanything"+msg.toLocaleUpperCase())

            }

 

            window.message={

                dosomething:dosomething,

                doanything:doanything

            }

       })(window)

       message.doanything() //doanythingSJW

       message.dosomething()//dosomethingSJW

 

6)闭包的缺点

* 函数执行完后,函数内部的局部变量没有释放,占用内存时间变成

* 容易造成内存泄漏(空间占用着不使用,其他的变量也没法使用,这就是内存泄漏)

解决办法:

* 能不用就不用(不现实)

* 及时释放 f=null

 

7)内存溢出和内存泄漏

*内存溢出:

* 一种程序运行出现的错误

* 当程序运行需要的内存超过剩余的内存时,就抛出内存溢出的错误

* 内存泄漏

* 占用的内存没有及时释放

* 内存泄漏积累的多了就容易导致内存溢出

* 意外的全局变量(直接赋值相当于全局变量 a=3)会造成内存泄漏

* 启动循环定时器后不清理容易造成内存泄漏

* 闭包会造成闭包泄漏 (f=null释放掉,不释放就造成泄漏)

 

8)面试题

 var name="the window"

        var object={

            name:"my object",

            getNameFunc:function(){

                return function(){

                    return this.name

                }

            }

        }

        alert(object.getNameFunc()()) //the window

 

        var name2="the window"

        var object2={

            name2:"my object2",

            getNameFunc:function(){

                var that=this

                return function(){

                    return that.name2

                }

            }

        }

        alert(object2.getNameFunc()()) //the object2

-----------------------------------------------------------------------------

function fun(n,o){

        console.log(o)

        return{

            fun:function(m){

                return fun(m,n)

            }

        }

    }

    var a=fun(0)

    a.fun(1)

    a.fun(2)

    a.fun(3)

 

    var b=fun(0).fun(1).fun(2).fun(3)

 

    var c=fun(0).fun(1)

    c.fun(2)

    c.fun(3)

 

5、对象创建模式

1)Object构造函数模式

* 先创建空Object对象,再动态添加属性方法

* 适用场景:起始对象的数据是不确定的

* 问题:语句太多

2)对象字面量模式

*{ }创建对象,指定属性方法

* 适用场景:起始时内部的数据是确定的

* 问题:创建多个对象,有重复代码

3)工厂模式(生产一个新的对象,不常用)

* 通过工厂函数动态创建对象并返回

function createPerson(name,age){

var obj={

name:name,

age:age

setName:function(name){

this.name=name

}

}

return obj

}

var p1=createPerson("Tom",12)

var p2=createPerson("Jack",15)

* 适用场景:创建多个对象

* 问题:对象没有一个具体的类型,都是Object类型

4)自定义构造函数类型

function Person(name,age){

this.name=name

this.age=age

this.setName:function(name){

this.name=name

}

}

var p1=new Person("jack",20)

* 适用场景:创建多个不同类型的对象

* 问题:内存的浪费,因为方法都一样,在每个实例对象上

5)构造函数+原型的组合模式

* 套路:自定义构造函数,属性在函数中初始化,方法添加到原型对象上

* 适用场景:需要多个类型确定的对象

function Person(name,age){

this.name=name

this.age=age

}

Person.prototype.setName=function(name){

this.name=name

}

 

6、继承模式

1)原型链继承

2)组合继承(原型链+借用构造函数的组合继承)

* 利用原型链实现对父类型对象的方法继承

* 利用super( )借用父类型构造函数初始化相同

 //父亲

       function Person(name,age){

           this.name=name

           this.age=age

       }

       //把方法放在父亲的原型链上 

       Person.prototype.setName=function(name){

           this.name=name

       }

       //子类型 其中call实现了子类用假继承操作属性

       function Student(name,age,price){

           Person.call(this,name,age)

           this.price=price

       }

  //子类型的原型是父类的实例--实现了继承 通过原型链继承使得子类可以使用父类的方法

       Student.prototype = new Person()

       //修正constructor属性???

       Student.prototype.constructor=Student

       //子类的方法放在父类的实例上 

       Student.prototype.setPrice=function(price){

            this.price=price

       }

 //新建了Student实例 但是他的原型相当于父类的实例 父类的实例又指向父类的原型 构成原型链

       var s=new Student("Tom",24,16000)

       //父类的属性和方法都能用

       console.log(s.name,s.price,s.age) //Tom 16000 24 

       //因此可以使用父类的方法

       s.setName("Jack")

       //放在父类实例上的自己的方法

       s.setPrice(1000)

       console.log(s.name,s.price,s.age) //Jack 1000 24

 

7、线程机制和事件机制

1)进程和线程

* 进程:程序的一次执行,他占有一片独立的空间

* 线程:是进程内的一个独立执行单元,是程序执行的一个完整流程,CPU的最小调度单元

* 进程中的多线程,数据可以共享;而不同进程之间的数据不可以共享

* js是单线程 (但是H5中的Web Workers可以多线程运行)

* 浏览器运行是多线程运行的

2)定时器是如何实现的?

* 定时器并不能保证真正定时执行

* 一般会延迟一丁点(可以接受),也可能延迟很长时间(无法接受) 先执行for等耗费时间

* 事件循环模型

3)js是单线程执行的/事件循环模型

* alert( )会暂时当前主线程的执行,同时暂停时间计时,点击确认后恢复执行

事件循环:从任务队列中循环取出回调函数放入执行栈中处理(一个接一个)

具体见宏队列,微队列笔记等等

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值