js基础知识 js复习 一、原型和原型链 二、作用域、闭包 三、异步和单线程 四、其他知识

js知识点介绍

基础知识

1、原型、原型链

2、作用域、闭包

3、异步单线程

jsAPI

1、DOM操作

2、AJax

3、事件绑定

开发环境

1、版本管理

2、模块化

3、打包工具

运行环境

1、页面渲染

2、性能优化

一、原型和原型链

1、构造函数

<script>
    function Foo(name,age){
        this.name = name;
        this.age = age;
        this.class = 'class-1';
        // return this; 默认有这一行
    }
    var f = new Foo('zhangsan',20);
    var f1 =new Foo('lisi',22); //创建多个对象
</script>

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、原型链

js基础知识
js复习
一、原型和原型链
二、作用域、闭包
三、异步和单线程
四、其他知识

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('<p>hello world').on('click',function(){
        alert('clicked')
    }).html('<p>javascript</p>')

二、作用域、闭包

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)、callapplyind

      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请求、动态js基础知识
js复习
一、原型和原型链
二、作用域、闭包
三、异步和单线程
四、其他知识加载

  • 3、事件绑定

  • ajax请求代码示例

      console.log('start')
      $.get('/data.json',function(data1){
      	console.log(data1);
      }
      console.log('end');//start end data1
    
  • js基础知识
js复习
一、原型和原型链
二、作用域、闭包
三、异步和单线程
四、其他知识加载示例

      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请求、动态js基础知识
js复习
一、原型和原型链
二、作用域、闭包
三、异步和单线程
四、其他知识加载
  • 事件绑定

四、其他知识

知识点

  • 日期、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 '<br>'+item+'</b>'
      })
      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
})