前端javascript总结笔记(一)--js的三座大山

前言:

第一章为变量类型和计算。

第二章到第四章分别是原型与原型链,作用域及闭包,异步和单线程,这三个就是我们说的三座大山。

一、变量类型和计算

1:JS中使用typeof能得到哪些类型?

字符串(String)、数值(Number)、布尔值(Boolean)、Undefined、[Null对象,数组(Array),函数(Function) ](Object)共5种

2:何时使用===,何时使用==

两等:当数据类型不一样时,会发生强制转换,然后比较值是否相等
三等:数据类型相同,数据的值也相同,不会发生类型转换,才能为true
除了if(obj.a == null){}用(==),其余情况建议用(===),因为jq源码是这么写的

3:js中有哪些内置函数

Object、Array、Boolean、Number、String、Function、Date、RegExp、Error

4:js变量按照存储方式区分哪些类型,并描述其特点

答:按储存方式区分变量类型:

值类型:字符串(String)、数值(Number)、布尔值(Boolean)、Undefined、Null

这6个占用空间固定,保存在内存空间(栈)中/保存与复制的是值本身/使用typeof检测数据的类型

引用类型:对象(Object)、数组(Array)、函数(Function)

这3个占用空间不固定,保存在堆中/保存与复制的是指向对象的一个指针/使用instanceof检测数据类型/使用new()方法构造出的对象是引用型

js中,值传递不会改变值,引用类型传递会改变指针指向,会改变他的值

 

5:如何理解json

JSON :JSON和Math一样都是内置对象 JSON也是一种数据格式 有两个API如下面所示:

JSON.stringify({a:10,b:20})//将object=>string

JSON.parse('{a:10,b:11}')//把字符串变为对象

附加:强制类型转换?

值类型可以进行强制类型转换。

1. 字符串拼接:把数字和bool值转为字符串。

2. == 运算符:

3. if语句判断条件中:都转为bool值

4. 逻辑运算符 && || :把运算符左侧的值转为bool

5.查看变量转为何种bool值:!!变量名

6.其中 0,空字符串'',NaN,null,undefined 都会转为false,而其他都会被转为true undefined is 值类型,null是引用类型

 

二、原型和原型链-构造函数

题目:

1.如何判断一个变量是数组类型?

var arr = [];
arr instanceo Array//true
typeof arr//数组属于object,用typeof是无法判断是否为数组的

2.写一个原型链继承的例子?

//第一个例子
//animal
function Animal(){
    this.eat = function(){
        console.log('animal eat')
    }
}    
//dog
function Dog(){
    this.bark = function(){
        console.log('dog bark')
    }
}
Dog.prototype = new Animal()
//金毛犬
var jinmaoquan = new Dog()
</script>

 

//第二个例子
function Elem(id){
    this.elem = document.getElementById(id); 
                }    
    Elem.prototype.html = function(val){
        var elem = this.elem;
        if(val){
            elem.innerHTML = val;
            return this;
        }else{
            return elem.innerHTML;
        }
    }

    Elem.prototype.on = function(type,fn){
        var elem = this.elem;
        elem.addEventListener(type,fn);
    }
    var div1 = new Elem('div1');
    div1.html('<p>hello imooc</p>');
    div1.on('click',function(){
        alert('clicked');
    })

3.描述new一个对象的过程?

new关键字创建对象的过程:

1.创建一个新的对象;
2.将新创建的对象的原型指向“构造函数的原型”;
3.this指向新创建的对象;
4.返回新创建的对象;

function Foo(name,age){
    this.name = name
    this.age = age
    this.class = "class_class"
    //return this // 默认有这一行
}
var f = new Foo("zhangsan",20)

 

4.zepto(或其他框架)源码种如何使用原型链?

主要去理解源码把,阅读,不要埋头苦读,zepto源码

知识点:

1.构造函数

1.构造函数的特点:

a:构造函数的首字母必须大写,用来区分于普通函数

b:内部使用的this对象,来指向即将要生成的实例对象

c:使用New来生成实例对象

 

2.构造函数扩展

构造函数-扩展

var a = {} 其实是 var a = new Object()的语法糖//构造函数为Object

var a = [] 其实是var a = new Array()的语法糖//构造函数是Array

function Foo{...}其实是var Foo =new Function(...)的语法糖//构造函数是Function

使用instanceof判断一个函数是否是一个变量的构造函数(如判断一个变量是否为“数组”,用instanceo Array)

3.原型规则和示例--5个原型规则

1.所有的引用类型(数组,对象,函数),都具有对象特性,即可自由扩展属性(除了“null”以外)

2.所有的引用类型(数组,对象,函数),都有__proto__(隐式原型)属性,属性值是一个普通对象

3.所有的函数,都有一个prototype(显式原型)属性,属性值也是一个普通的对象

4.所有的引用类型(数组,对象,函数),__proto__属性值指向它的构造函数的“prototype”属性值

//1-4
var obj = {};obj.a = 100;
var arr = [];arr.a = 100;
function fn(){};fn.a = 100;

console.log(obj.__proto__);
console.log(arr.__proto__);
console.log(fn.__proto__);

console.log(fn.prototype);

console.log(obj.__proto__ === Object.prototype)

5.当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的__proto__(即它的构造函数的prototype)中寻找

//5
//构造函数
function Foo(name,age){
    this.name = name;
}
Foo.prototype.alertName = function(){
    alert(this.name);
}
//创建实例
var f = new Foo('lisi');
f.printName = function(){
    console.log(this.name);
}
//测试
f.printName();//这个对象本身有这个属性
f.alertName();//这个对象本身没有这个属性

 

4.原型链

首先 对象的隐式原型指向构造函数的显式原型,原型是一个普通对象,所以存在一个原型类,对象不存在的属性到对象的隐式原型去找。

5.instanceof

instanceof是判断引用类型属于那个构造函数 的。

instanceof 的判断逻辑:

f的“__proto__”一层一层往上,能否对应到Foo.prototype ,再试着判断f instanceof Object

附加:判断自身是否有这个属性

var item
for (const key in object) {
    //判断是否时自己属性和不是原型属性
    if (object.hasOwnProperty(key)) {
        const element = object[key]; 
    }
}

三、作用域与闭包

题目:

1.说一下对变量提升的理解?

见下面知识点执行上下文

2.说明this几种不同的使用场景?

见下面知识点this的4个使用场景

3.创建10个<a></a>标签,点击的时候弹出对应的序号

for(var i = 0;i < 10;i++){  
    var a = document.createElement("a");
    a.innerHTML = "love" + i + "<br>";
    (function(j){
        a.onclick = function(e){
            e.preventDefault();//阻止浏览器默认事件,如href的链接跳转
            alert(j);
    }
    })(i)
    document.body.appendChild(a);

 

4.如何理解作用域?

见下面知识点

5.实际开发中闭包的应用?

    //闭包实际应用中主要用于封装变量,收敛权限,就是说存入数组里面有没有此项,没有则添加,有则不添加
    function isFirstLoad(){
        var _list = []
        return function(id){
            // _list.indexOf(id)返回的是数组的索引
            if(_list.indexOf(id) >= 0){
                return false
            }else{
                _list.push(id)
                return true
            }
        }
        
    }
    //使用
    var firstLoad = isFirstLoad()
    console.log(firstLoad(110))//true
    console.log(firstLoad(110))//false
    console.log(firstLoad(520))//true

知识点:

1.执行上下文

  • 范围:一段<script>或者一个函数;
  • 全局:变量定义、函数声明;
  • 函数:变量定义、函数声明、this、arguments 

定义函数有两种方式:函数声明以及函数表达式(函数声明的一个重要特征:函数声明提升)

小tip:区分“函数声明”以及“函数表达式”

函数声明: function fn(){}

函数表达式: var fn = function(){}

例子:

console.log(a)//underfined
var a =100

fn("hansen")//"hansen" 22
function fn(name){
    age = 22
    console.log(name,age)
    var age
}

解释:在全局首先var a 和 function fn先拿出来占位(变量提升)。在函数体中,var age拿出来先占位(变量提升),故函数体里面也不会报错。日常生活中不要这么用。

2.this

1.this要在执行时才能确认值,定义时无法确认

代码:

var a = {
	name: "long",
	fn: function () {
		console.log(this.name);//就是这里有bug 在定义时也无法确定
	}
}

a.fn();// this === a
a.fn.call({name: "gong"})// this === {name: "gong"}
var fn1 = a.fn;
fn1(); // this === window (执行)

2.this 作为构造函数执行,作为对象属性执行, 作为普通函数执行, call apply bind

代码:


//构造函数
function Foo(name){
//this = {};
 this.name = name;
//return this;
}
var f = new Foo('zhangsan');

//作为一个对象的属性
var obj = {
       name : 'A',
printName:function(){
   console.log(this.name);
}
}
//普通函数的this
function fn(){
   console.log(this);
}
fn()// window

//call apply bind
function fruit(){
console.log(this.name+'---'+this.color);
}
var fn1 = {name : '香蕉',color:'黄色'} 
var fn2 = {ame : '橘子',color : '橙色'}
fruit.call(fn1);
fruit.apply(fn2);

var fn3 = {name : '苹果',color : '红色'}
var fruit  = function(){
    console.log(this.name+'---'+this.color); 
}.bind(fn3)
fruit()

 

3.作用域

1.无块级作用域

    if(true){
        var name = "Hansen";
    }
    console.log(name);//Hansen

2.函数和全局作用域

    var a = 100
    function fn(){
        var a = 200
        console.log("fn",a)
    }
    console.log("global",a)
    fn()
    //global 100
    //fn 200

补充:ES6是有块级作用域的

//写在花括号里面定义的内容,块级作用域外是不能调用的
if(true){
let a = 10;
}
console.log(a);//报错:a没有定义

 

4.作用域链

当前作用域没有定义的变量,即“自由变量”

    var a = 100
    var c = 300
    function fn(){
        var b = 200
        console.log(a)//自由变量
        console.log(b)
        console.log(c)//自由变量
    }
    fn()

 

5.闭包

一、一个函数的父级作用域是在它定义的时候的作用域,而非它执行时候的作用域。

二、闭包

1.定义:闭包是一个函数和函数所声明的词法环境的结合。

2.应用场景:模块化、封装。

3.优点:封装性强,使得变量始终保持在内存中。

4.缺点:内存的消耗导致的性能问题。

5.闭包创建:函数嵌套函数,使得内部函数返回出去,让外部来访问内部的变量。

三、闭包的使用场景

1.函数作为一个返回值 。

    function F1(){
        var a = 100;
        return function(){
            console.log(a);
        }
    }
    var f1 = F1();
    var a = 200;
    f1();

2.函数作为参数传递。

    function F1(){
        var a = 100
        return function(){
            console.log(a)//a 是自由变量,向父级作用域寻找
        }
    }
    var f1 = F1()
    function F2(fn){
        var a = 300
        fn()
    }
    F2(f1)//100

 


四、异步与单线程

题目:

1.同步和异步的区别是什么?分别举一个同步与异步的例子

见下面知识点1

2.一个关于setTimeout的笔试题

    console.log(1)
    setInterval(function(){
        main.innerHTML += Math.floor(Math.random()*10) + ' ';
    },1000)
    console.log(3)
    setInterval(function(){
        main.innerHTML += Math.floor(Math.random()*10) + '* ';
    },2000)
    console.log(5)

//1 3 5 (然后1000mm的执行一次,然后1000mm和2000mm的同时执行一次,以此类推)

3.前端使用异步的场景有哪些

见下面知识点

知识点:

1.什么是异步(对比同步)

同步会阻塞后续程序代码的执行,而异步不会阻塞程序的运行。

何时需要异步:

1. 在可能发生等待的情况:在等待的过程中程序仍然要执行其他操作。

2. 等待过程中不能像 alert 一样阻塞程序运行。

3.所有的“等待的情况”都需要异步

异步例子:

    console.log(100);
    setInterval(function(){
        console.log(200)
    },1000);
    console.log(300);
//首先他会打印100,由于到了200时发生等待,所以先执行300,最后执行200

同步例子:

    console.log(1314);
    alert("Hansen真帅");
    console.log(520);
//由于执行时候有alert会卡顿,所以他是同步的

 

2.前端使用异步的场景 

1. 定时任务:setTimeout,setInterval

    console.log(100);
    setInterval(function(){
        console.log(200)
    },1000);
    console.log(300);

2. 网络请求:ajax 请求,动态 <img> 加载、脚本等文件下载和加载。

    console.log('start')
    $.get('test3.json',function(data){
        console.log(data)
    })    
    console.log('end')
//需要打开apa服务器,test3.json为模拟数据[{
//   "a":10,
//   "b":20
//},
//{
//   "c":10,
//   "d":20
//}]

3. 事件绑定

    console.log('start');
    document.getElementById('btn1').addEventListener('click',function(){
        console.log('ing');
    });
    console.log('end');

 

 

3.异步和单线程

由于js是单线程,在代码执行的时候又不能因为执行需要等待的代码而造成阻塞,因此js会首先将无需等待的(同步)的代码执行完成后,来处理异步的代码,如果达到异步代码的执行条件的话,就会执行。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值