献给前端求职路上的你们(JS)

1、函数与数据类型

[Undefined,Null,Boolean,Number,String,Object]

(1)var 预编译,当前作用域内的变量声明被提前到作用域顶部,但赋值保留在原处。
(2)函数声明提前分两种

函数声明

 function a();
  • 1

函数表达式

var a = function();
  • 1

只有var a被提前; //还是undefined,不能先调用。
(3) Null==undefined null是一个object, undefined是一个windows对象,Undifeind

(4)method.call(this, arg1,arg2), method.apply(obj,[arg1,arg2..])或者直接是arguments对象。两者的作用都是改变函数的运行环境,执行上下文。[1]改变函数执行上下文,将this指向一个obj对象。
(5)匿名函数。
(function(a,b))–匿名函数的引用,
(function(a,b))(c,d)函数的调用,jQuery就是一个匿名函数。
全局变量是魔鬼,匿名函数执行一次就被销毁了,不会在内存中驻留,不会造成全局变量污染。
注意与闭包的区别,其实两者就没关系。

2、 Javascript作用域链

(1)JavaScript并没有块及作用域,只有函数级作用域:变量在声明它们的函数体及其子函数内是可见的。函数唯一拥有自身作用域的结构(for 循环没有自身作用域)。
(2)代码在一个环境中执行的时候,会创建变量对象的一个作用域链,来保证变量的有序访问,作用域链的第一个对象是当前执行的环境,下一个是父函数的执行环境—>直到最外边一个全局作用域,这个链叫作用域链。

(3)js解析是沿着作用域链一级一级搜索的过程,从第一个对象开始,逐级向后回溯直到window对象,找到同名标识符停止,找到后不再继续遍历,找不到就报错。父函数定义的变量在子函数的作用域链中,子函数没有被销毁,其作用域链中所有变量和函数就会被维护,不会被销毁(闭包的原理)

3、 javascript原型继承与原型链

(1)每个函数都有一个prototype属性(new出来的普通对象是_proto_属性),都会指向该对象的原型对象Person.prototype. 当我们用构造函数new一个实例后,从原型对象继承属性和方法。

(2)为什么prototype?因为不prototype话,new两个对象,对象里的属性和方法同名,但确实不同的引用,对属性来说,没问题,但是对同名的方法,功能是一样,却一直在复制一样的东西,这就要prototype。两个数组push,一个操作不影响另外一个。自己的属性和方法在构造器中用this,公用的方法用prototype;

(3)原型链:当代码去读取某个对象的属性是,会执行一遍搜索,先从对象本身的属性查找,如果没有,则从对象的原型对象查找,在没有原型对象prototype上查找。。。知道
object原型上没有就报错,因为object的原型是null。
p—p原型—p原型的原型-obj hasOwnProperty()
(4)继承:子类继承父类的属性和方法,将父类的实例复制给子类的原型,或者调用apply或者call方法。

4、 闭包(闭的是谁?)

(1)闭包是指在 JavaScript 中,内部函数总是可以访问其所在
的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。内部function会闭外部function的局部变量直到内部function结束。这意味着当前作用域总是能够访问外部作用域中的变量。举个实例吧:

function a() {
    var i = 0;
    function b() { alert(++i); }
    return b;
}
var c = a();
c();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

原理:根据js垃圾回收机制,标记清除,引用清除嘛。
利用这个特性,刚好 a–>b —>c引用着。这样被引的着就不会被回收了,因为b的执行,依赖a,所以a的变量,没有被回收。

(2)好处。

  • [1]避免全局变量的污染,因为不加var就是全局变量,这样的临时变量是GV,有很多坏处,有些只要执行一次,组件初始化。我们可以用闭包,构建匿名自执行函数,执行完很快就被释放了。return该要的东西就行。

  • [2]缓存,一个处理很耗时的函数对象,每次调用都花费很好的时间,我们只要将计算出来的值存储起来,当下次调用的是要,先查找,有就直接用,没有再计算并存起来。闭包刚好,利用这一点,因为他不会释放外部的引用,内部函数的值得以保存。

  • [3]实现封装,防止变量跑到外面的作用域,造成命名冲突(和第一点类似)。
  • [4]模拟面向对象中的对象
function Person(){
    var name = "default";
    return {
        getName : function(){
        return name;
    },
    setName : function(newName){
        this.name = newName;
    }
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

(3)坏处,

  • [1]内存消耗,一般函数的活动对象会随着执行上下文一起销毁,但是闭包引用另外一个函数的活动对象,因此对象无法被销毁。垃圾回收是根据引用标记来销毁对象,如果最后一个属性没有被引用才会销毁改对象,这也意味着闭包需要更多的内存消耗。IE浏览器中,如果存在循环应用,可能会造成内存泄露的问题。
  • [2]闭包可能引起跨域访问,影响性能。如果一个跨作用域的对象被引用了一次以上,则先把它存储到局部变量里再使用。Var doc = document;

5、js事件流

从页面上接收到事件的顺序。IE事件流是事件冒泡,W3C事件流刚好相反是事件捕获

事件冒泡:假如单击了内层标签按钮,他会一层一层网上走,直到document。
事件捕获: 相反,从外到内,document->-body->div1-div2.
但是要使支持事件捕获addEventListener('click',function,true);第三个参数为true,默认false为事件冒泡。

(1) 事件处理的三个阶段:事件捕获,目标阶段,事件冒泡阶段,IE8不支持mp.
(2) 一个标签绑定多个事件

  • IE: attachEvent(“onclick”,function) – detach先绑定后触发,
  • W3C: addEventListener(“click”,function, false) remove先绑定先触发。
    区别btn.onclick=function 作用域是this—当前dom节点。attachEvent()中的this是windows.

(3)兼容性代码:

  • w3C事件对象是:event IE:windows.event
  • 事件目标event.target IE:windows.event.srcElement |currentTarget:当前正在处理的元素 target:目标元素
  • 取消默认行为:event.returnValue = false; IE:preventDefault
  • 事件冒泡:event.stopPropagation || event.cancleBubble = true;
function addEvent(obj, type , callback){
    if(windows.attachEvent{
        obj.attachEvent(“on”+type,callback)}
    else{
        obj.addEventListener(type,callback)
    }
}
function stopBubble(event){
    if(windows.event)
    {
        event.cancleBubble = true;
    }
    else{
        event.stopPropagation
    }
}

var table = document.getElementById( "table" );  
table.onclick = function( e ){  var e = e || window.event;
    var target = e.srcElement || e.target;      
    if( target.tagName.toUpperCase() == "td" ){ …. };  

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

(4)事件委托/代理:利用事件冒泡的原理,把事件处理器添加到1父级元素上
优:(1)可以节省大量内存的占用,减少事件注册,table—代理td
(2)新增子元素时,无需进行事件保定,动态部分很适合。
缺:不能什么都代理,很可能事件误判,劲酒虽好,不要贪杯哦。

6、Es6新特性

转译工具Traceur ,Babel 编译成ES5. 你们现在的项目中有用SE6的这些新特性吗?
(1)一些新增的api. [“a”,”b”,”c”].keys(),values(),entries()和map一样了。有集合Set, Map

(3)生成器genrators, function* qq(name){yield 暂停,}next()方法执行下一句。

(4)可变参数—代替arguments Map.set(document,”the document”); for (var [key,value] of map){…}

(5)箭头 Input(function的参数)=>Output(return…) 不要function,也不要return了array.filter(obj => job.isSelect()) 写一些回调函数的时候很好用array.filter(function(job){ return job.isSelect()});

(6)有代理Proxy, 还有类Class. 模块Moudules export import 导入 导出模块。

(7)有let,定义块级作用域,不会像var一样,作用域是函数体的全部,比如for 循环的变量i是共享的。

let是更完美的var,(1)有块级作用域,let最外面声明的不是全局变量,windows访问不到,let不能重定义。
const用于声明长粮食,在声明的时候赋值,不能修改。

7、 设计模式

js开发前端UI组件中会经常涉及,纯粹的页面业务逻辑可能涉及不多。公开出哪些方法,应该提供 哪些接口,哪部分逻辑流程应该开放出去让用户自行编写。如何实现高内聚低耦合,如何实现组件的高复用。常用的一些设计模式
- (1)单例模式:划分命名空间很好用。Var XGP={Util:{},CSS:{},Ajax:{}} 惰性单体:懒加载,return 判断没有在创建实例
(2)观察者模式: (3)职责链模式: (4)工厂模式:

8、组件开发

问题(1)复用性:通过继承来复用。改变的是一点点。属性:父类.call(this,) 方法继承原型=new 父类();
遇到的问题:(2)不同组件的传参是不一样的,怎么弄? 传递的顺序也不一样,构造一个json配置参数,有则用配置的参数,没有就用默认的。extend( this.settings , opt );

9. Js函数节流

主要思路是,通过一个定时器,阻断连续重复的函数调用。
特征:1. 短时间内连续多次重复触发 ; 2. 频繁的 DOM 操作,操作DOM代价大,在用户察觉范围外,降低函数调用的频率,从而提升性能。

function(){
    clearTimeout(timer);  
    timer = setTimeout(function () { 
        }, 100)};
  • 1
  • 2
  • 3
  • 4

JS模块化—-require.js/sea.js

优点:
(1) 防止js加载阻塞页面渲染。 Js中有alert();
(2) 更好的分离。一堆script脚本, html中只需引入一个主入口就好了。然后在依赖进来
(3) 更好的组织代码,大型项目的维护,多人开发,代码风格不一样,业务逻辑混杂,一个文件一个模块,这样控制了文件的粒度,一个萝卜一个坑。单一职责原则,体现OOP思想
(4) 按需加载,虽然js压缩在一个js中可以减少请求,但是只需依赖少数几个文件时,体积与数量的折中
(5) 避免命名冲突,闭包,匿名自执行函数, 模块化只向外面暴露该模块的接口。
(6) 更好的依赖管理,A依赖B,用A之前要script加载好B,如果过段时间不依赖B,依赖C,很难维护的。

缺点:
(1).系统分层,调用链会很长
(2).模块间通信,模块间发送消息会很耗性能 。如果有很多jquery插件,那这样要是实现一个很复杂的交互时,模块间的依赖会很多

requriejs 异步加载,依赖前置,提前执行
AMD是requirejs的模块化定义的的规范,CMD是sea.js模块化规范。
define 定义模块

 define([‘require’,’foo’],function(){return});     baseUrl + paths
  • 1

require加载模块 require([‘foo’,’bar’],function(foo,bar){});

非AMD模块输出,插件不符合符合AMD规范。 用功能:shim require.config({ shim{‘chajian’:exports|| deps:}})

Sea.js —同步加载,依赖就近,延迟执行
define 定义, exports导出,对外提供单个接口, define(function(require,exports,module){});
module上存储了当前模块的一些对象,可以直接导出一个对象。module.exports =a; 提供整个接口
require(./a)直接引入, require.async异步引入。 这就是 CMD 模块定义规范的所有内容。

猜你喜欢

转载自blog.csdn.net/A_BlackMoon/article/details/80368800