js基础知识

js复习

js知识点介绍

基础知识

1、原型、原型链

2、作用域、闭包

3、异步单线程

jsAPI

1、DOM操作

2、AJax

3、事件绑定

开发环境

1、版本管理

2、模块化

3、打包工具

运行环境

1、页面渲染

2、性能优化

一、原型和原型链

1、构造函数

2、构造函数--扩展

  • var a = {}其实是var a = new Object()的语法糖
  • var a = []其实是var a = new Array()的语法糖
  • function Foo(){...}其实是var Foo = new Function(...)的语法糖
  • 使用instanceof判断一个函数是否是一个变量的构造函数
  • 判断一个变量是否为“数组”
  • 变量 instanceof Array

3、原型规则和示例

5条原型规则

  • 原型规则是学习原型链的基础

  • 1、所有的引用类型(数组、对象、函数)都具有对象特性,即自由扩展特性(除了"null"以外)

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

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

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

  • 3、所有的函数,都有一个prototype属性,属性值也是一个普通对象。

    console.log(fn.prototype)

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

  • __proto__隐式类型原型

  • prototype显示类型原型

    console.log(obj.proto === Object.prototype)//true

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

    //构造函数
    function Foo(name,age){
    this.name = name;
    }
    Foo.prototype.alertName = function(){
    alert(this.name);
    }
    //创建实例
    var f = new Foo('zhangsan');
    f.printName = function(){
    console.log(this.name);
    }
    //测试
    f.printName();//zhangsan
    f.alertName(); //zhangsan

循环对象自身的属性 hasOwnProperty

var item;
for(item in f){
//高级浏览器已经在for in 屏蔽了来自原型的属性
if(f.hasOwnProperty(item)){
console.log(item);//name printName
}
}

4、原型链

5、instanceof

  • f instanceof Foo的判断逻辑是
  • f的__proto__一层一层往上,能否对应到Foo.prototype再试着判断f instanceof Object

问题

1、如何准确的判断一个变量是数组类型

var arr=[];
arr instanceof Array; //true
typeof arr; //Object,typeof是无法判断是否是数组的

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

//动物
function Animal() {
this.eat = function(){
console.log('animal eat');
}
}
//狗
function Dog(){
this.bark = function(){
console.log('dog bark');
}
}
Dog.prototype = new Animal();
var hashiqi = new Dog();//哈士奇

3、描述new 一个对象的过程

  • 创建一个新对象

  • this指向这个新对象

  • 执行代码即对this赋值

  • 返回this

    //构造函数
    function Foo(name,age){
    this.name = name;
    this.age = age;
    this.class = 'class-1';
    }
    var f = new Foo('zhangsan',20)

4、写一个dom查询的例子

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);
return this;
}
var div1 = new Elem('div1');
div.html('

hello world').on('click',function(){
alert('clicked')
}).html('

javascript

')

二、作用域、闭包

1、执行上下文

  • 1、范围:一段<script>或者一个函数

  • 2、全局:变量定义、函数声明一段<script>

  • 3、函数:变量定义、函数声明、this.argument函数

  • ps:注意函数声明和函数表达式的区别

    console.log(a);//undefined
    var a = 100;//函数声明
    fn('zhangsan'); //'zhangshan' 20
    function fn(name){//函数表达式
    age = 20;
    console.log(name,age)
    var age;
    }

2、this

  • this要在执行时才能确定值,定义时无法确定

    var a = {
    name: 'A',
    fn:function(){
    console.log(this.name);
    }
    }
    a.fn();//this === a
    a.fn.call({name:'B'});//this === {name:'B'}
    var fn1 = a.fn;
    fn1(); //this === window;

  • (1)、作为构造函数执行

    Function Foo(name){
    this.name = name;
    }
    var f = new Foo('zhangsan')

  • (2)、作为对象属性执行

    var obj = {
    name: 'A',
    printName:function(){
    console.log(this.name)
    }
    }
    obj.printName();

  • (3)、作为普通函数执行

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

  • (4)、call\apply\bind

    function fn1(name,age){
    alert(name);
    console.log(this);
    }
    fn1.call({x:100},'zhangsan',20)
    fn1.apply({x:100},['zhangsan',20])
    var f2 = function (name,age){
    alert(name);
    console.log(this);
    }.bind({y:200});
    fn2('zhangsan',20)

3、作用域

  • 1、没有块级作用域

  • 2、只有函数和全局作用域

    //无块级作用域
    if(true){
    var name = 'zhangsan';
    }
    console.log(name);//zhangsan

    //函数和全局作用域
    var a = 100;
    function fn(){
    var a = 200;
    console.log('fn',a)//fn 200
    }
    console.log('global',a)//global 100
    fn();

4、作用域链

var a = 100;
function fn(){
var b = 200;
//当前作用域没有定义的变量,即自由变量
console.log(a)//100
console.log(b)//200
}
fn()

5、闭包

function F1(){
var a = 100;
//返回一个函数(函数作为返回值)
return function(){
console.log(a)//100自由变量父作用域寻找
}
}
//得到一个函数
var f1 = F1();
var a = 200;
f1();

6、闭包的使用场景

  • 1、函数作为返回值

  • 2、函数作为参数传递

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

问题

1、说一下变量提升的理解

  • 变量升级 变量是在存储信息的容器

  • 函数声明(注意和函数表达式的区别)

  • 变量提升就是,在变量的作用域内,不管变量在何处声明,都会提升到作用域的顶部,但是变量初始化的顺序不变。

    function test(){
    a = 1;
    b = 2;
    var a b;
    console.log(a)
    console.log(b)
    }

2、说明this几种不同的场景

  • 1、构造函数执行
  • 2、作为对象属性执行
  • 3、作为普通函数执行
  • 4、call、apply、bind

3、如何理解作用链

  • 自由变量
  • 作用域链,即自由变量的查找
  • 闭包的两个场景

实际开发中闭包的应用

//闭包实际应用中主要封装变量,收敛权限
function isFirstLoad(){
var _list = [];
return function(id){
if(_list.indexOf(id)>=0){
return false;
}else {
_list.push(id);
return true;
}
}
}
//使用
var firstLoad = isFirstLoad();
firstLoad(0);//true
firstLoad(10);//false
firstLoad(20);//true
//你在isFirstLoad函数外面,根本不可能修改掉_list的值

三、异步和单线程

  • 什么是异步(对比异步)
  • 前端使用用异步的场景
  • 异步和单线程

1、什么是异步

console.log(100);
setTimeout(function(){
console.log(200)
},1000);
console.log(300);
//100 300 200顺序
//对比同步 同步会有阻塞
console.log(100);
alert(200);//几秒中之后单击确认
console.log(300);
//100 200 300

2、何时需要异步

  • 在可能发生等待的情况
  • 等待过程不能像alert一样阻塞程序运行,因此,所以的“等待的情况”都需要异步。

3、前端使用异步的场景

  • 1、定时任务:setTimeout、setInverval

  • 2、网络请求:ajax请求、动态加载

  • 3、事件绑定

  • ajax请求代码示例

    console.log('start')
    $.get('/data.json',function(data1){
    console.log(data1);
    }
    console.log('end');//start end data1

  • 加载示例

    cosnole.log('start');
    var img = document.createElement('img');
    img.onload = function(){
    console.log('loaded')
    }
    img.src = '/xxx.png';
    console.log('end');//start end loaded

  • 事件绑定示例

    cosnole.log('start');
    document.getElementById('btn1').addEventListener('click',function(){
    alert('clicked');
    })
    console.log('end');
    //start end clicked

4、异步和单线程

console.log(100);
setTimeout(function(){
console.log(200);
})
console.log(300);
//100 300 200

  • 1.执行第一行,打印100。
  • 2.执行setTimeout后传入setTimeout的函数会被暂存起来,不会立即执行(单线程的特点,不能同时干两件事)。
  • 3.执行最后一行打印300。
  • 4.待所有程序执行完,处于空闲状态时,会立马看有没有暂存起来的要执行。
  • 5.发现暂存起来的setTimeout中的函数无需等待时间,就立即来过来执行。

问题

1、同步和异步区别是什么

  • 1.同步会阻塞代码执行,而异步不会
  • 2.alert是同步,setTimeout是异步

2、一个关于setTimeout的笔试题

console.log(1);
setTimeout(function(){
console.log(2);
},0)
console.log(3);
setTimeout(function(){
console.log(4)
},1000)
console.log(5);
//1 3 5 2 4

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

  • 定时任务:setTimeout、setInverval
  • 网络请求:ajax请求、动态加载
  • 事件绑定

四、其他知识

知识点

  • 日期、Math、数组API、对象API

1、日期

  • Date.now() //获取当前时间的毫秒数
  • var dt = new Date();
  • dt.getTime(); //获取毫秒数
  • dt.getFullYear(); //年
  • dt.getMonth();//月(0-11)
  • dt.getDate(); //日(0-31)
  • dt.getHours();//小时(0-23)
  • dt.getMinutes();//分钟(0-59)
  • dt.getSeconds();//秒(0-59)

2、Math

  • 获取随机数Math.random()

3、数组API

  • forEach 遍历所有元素

  • every 判断所有元素是否都符合条件

  • some 判断是否有至少一个元素符合条件

  • sort 排序

  • map 对元素重新组装,生成新数组

  • filter 过滤符合条件的元素

  • forEach

    var arr = [1,2,3]
    arr.forEach(function(item,index){
    //遍历数组的所有元素
    console.log(index,item)
    })

  • every

    var arr = [1,2,3];
    var result = arr.every(function(item,index){
    //用来判断所有的数组元素,都满足一个条件
    if(item<4){
    return ture
    }
    })
    console.log(result)//true

  • some

    var arr = [1,2,3];
    var result = arr.some(function(item,index){
    //用来判断所有的数组元素,只要有一个满足条件即可
    if(item<2){
    return true
    }
    })
    console.log(result)//true

  • sort

    var arr = [1,4,2,3,5];
    var arr2 = arr.sort(function(a,b){
    //从小到大排序
    return a-b
    //从大到小的排序
    return b-a
    })
    console.log(arr2);

  • map

    var arr = [1,2,3,4];
    var arr2 = arr.map(function(item,index){
    //将元素重新组装,并返回
    return '
    '+item+''
    })
    console.log(arr2)

  • filter

    var arr = [1,2,3];
    var arr2 = arr.filter(function(item,index){
    //通过某一个条件过滤数组
    if(item>=2){
    return true
    }
    })
    console.log(arr2);//2 3

4、对象API for in

var obj = {x:100,y:200,z:300};
var key;
for(key in obj){
if(obj.hasOwnProperty(key)){
console.log(key,obj[key])
}
}
//x, 100;y ,200;z,300

解题

1、获取2019-02-16(当前时间)

function formatDate(dt) {
if(!dt){
dt = new Date();
}
var year = dt.getFullYear();
var month = dt.getMonth()+1;
var date = dt.getDate();
if(month < 10){
//强制类型转换
month = '0'+month;
}
if(date <10){
//强制类型转换
date = '0'+date;
}
//强制类型转换
return year + '-'+month + '-'+date;
}
var dt = new Date();
var formatDate = formatDate(dt);
console.log(formatDate);//2019-02-16

2、获取随机数,要求是长度一致的字符串格式

var random = Math.random();
random = random + '0000000000'//后面加上10个0
random = random .slice(0,10);
console.log(random)

3、写一个能遍历对象和数组的forEach函数

function forEach(obj,fn){
var key;
if(obj instanceof Array){
//准确判断是否是数组
obj.forEach(function(item,index){
fn(index,item);
})
}else {
//不是数组就是对象
for(key in obj){
if(obj.hasOwnProperty(key)){
fn(key,obj[key])
}
}
}
}
var arr = ['苹果','香蕉','梨'];
//注意,这里的参数的顺序换了,为了和对象的遍历格式一致
forEach(arr,function(index,item){
console.log(index,item)
// 0 "苹果"
// 1 "香蕉"
// 2 "梨"
})
var obj = {x:100,y:200};
forEach(obj,function(key,value){
console.log(key,value)
// x 100
// y 200
})

posted @ 2019-02-17 22:50  不完美的完美  阅读(493)  评论(0)    收藏  举报