1. 你觉得jQuery或zepto源码有哪些写的好的地方

jquery源码封装在一个匿名函数的自执行环境中,有助于防止变量的全局污染,
然后通过传入window对象参数,可以使window对象作为局部变量使用,好处是当jquery中访问window对象的时候,就不用将作用域链退回到顶层作用域了,从而可以更快的访问window对象。
同样,传入undefined参数,可以缩短查找undefined时的作用域链

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
(function( window, undefined ) {
    //用一个函数域包起来,就是所谓的沙箱

    //在这里边var定义的变量,属于这个函数域内的局部变量,避免污染全局

    //把当前沙箱需要的外部变量通过函数参数引入进来

    //只要保证参数对内提供的接口的一致性,你还可以随意替换传进来的这个参数

    window.jQuery = window.$ = jQuery;
})(window);
  1. jquery将一些原型属性和方法封装在了jquery.prototype中,为了缩短名称,又赋值给了jquery.fn,这是很形象的写法
  2. 有一些数组或对象的方法经常能使用到,jQuery将其保存为局部变量以提高访问速度
  3. jquery实现的链式调用可以节约代码,所返回的都是同一个对象,可以提高代码效率

2. jQuery 的实现原理?

  1. (function(window, undefined) {})(window);
  2. jQuery 利用 JS 函数作用域的特性,采用立即调用表达式包裹了自身,解决命名空间和变量污染问题
  3. window.jQuery = window.$ = jQuery;
  4. 在闭包当中将 jQuery 和 $ 绑定到 window 上,从而将 jQuery 和 $ 暴露为全局变量

3. jQuery.fn 的 init 方法返回的 this 指的是什么对象? 为什么要返回 this?

  1. jQuery.fn 的 init 方法 返回的 this 就是 jQuery 对象
  2. 用户使用 jQuery() 或 $() 即可初始化 jQuery 对象,不需要动态的去调用 init 方法

4. jQuery.extend 与 jQuery.fn.extend 的区别?

  1. $.fn.extend() 和 $.extend() 是 jQuery 为扩展插件提拱了两个方法
  2. $.extend(object); // 为jQuery添加“静态方法”(工具方法)
1
2
3
4
5
6
$.extend({
  min: function(a, b) { return a < b ? a : b; },
  max: function(a, b) { return a > b ? a : b; }
});
$.min(2,3); //  2
$.max(4,5); //  5
  1. $.extend([true,] targetObject, object1[, object2]); // 对targt对象进行扩展
1
2
3
4
var settings = {validate:false, limit:5};
var options = {validate:true, name:"bar"};
$.extend(settings, options);  // 注意:不支持第一个参数传 false
// settings == {validate:true, limit:5, name:"bar"}
  1. $.fn.extend(json); // 为jQuery添加“成员函数”(实例方法)
1
2
3
4
5
6
7
8
$.fn.extend({
    alertValue: function() {
        $(this).click(function(){
            alert($(this).val());
        });
    }
});
$("#email").alertValue();

5、jQuery 的属性拷贝(extend)的实现原理是什么,如何实现深拷贝?

  1. 浅拷贝(只复制一份原始对象的引用)
    var newObject = $.extend({}, oldObject);
  2. 深拷贝(对原始对象属性所引用的对象进行进行递归拷贝)
    var newObject = $.extend(true, {}, oldObject);

6、jQuery 的队列是如何实现的?队列可以用在哪些地方?

  1. jQuery 核心中有一组队列控制方法,由 queue()/dequeue()/clearQueue() 三个方法组成。
  2. 主要应用于 animate(),ajax,其他要按时间顺序执行的事件中
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
var func1 = function(){alert('事件1');}
var func2 = function(){alert('事件2');}
var func3 = function(){alert('事件3');}
var func4 = function(){alert('事件4');}

// 入栈队列事件
$('#box').queue("queue1", func1);  // push func1 to queue1
$('#box').queue("queue1", func2);  // push func2 to queue1

// 替换队列事件
$('#box').queue("queue1", []);  // delete queue1 with empty array
$('#box').queue("queue1", [func3, func4]);  // replace queue1

// 获取队列事件(返回一个函数数组)
$('#box').queue("queue1");  // [func3(), func4()]

// 出栈队列事件并执行
$('#box').dequeue("queue1"); // return func3 and do func3
$('#box').dequeue("queue1"); // return func4 and do func4

// 清空整个队列
$('#box').clearQueue("queue1"); // delete queue1 with clearQueue

7、jQuery 中的 bind(), live(), delegate(), on()的区别?

  1. bind 直接绑定在目标元素上
  2. live 通过冒泡传播事件,默认document上,支持动态数据
  3. delegate 更精确的小范围使用事件代理,性能优于 live
  4. on 是最新的1.9版本整合了之前的三种方式的新事件绑定机制

8、是否知道自定义事件? jQuery 里的 fire 函数是什么意思,什么时候用?

  1. 事件即“发布/订阅”模式,自定义事件即“消息发布”,事件的监听即“订阅订阅”
  2. JS 原生支持自定义事件,示例:
1
2
3
4
document.createEvent(type); // 创建事件
event.initEvent(eventType, canBubble, prevent); // 初始化事件
target.addEventListener('dataavailable', handler, false); // 监听事件
target.dispatchEvent(e);  // 触发事件
  1. jQuery 里的 fire 函数用于调用 jQuery 自定义事件列表中的事件

9、jQuery 通过哪个方法和 Sizzle 选择器结合的?

  1. Sizzle 选择器采取 Right To Left 的匹配模式,先搜寻所有匹配标签,再判断它的父节点
  2. jQuery 通过 $(selecter).find(selecter); 和 Sizzle 选择器结合

10、jQuery 中如何将数组转化为 JSON 字符串,然后再转化回来?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14

$.array2json = function(array) {
    // 通过原生 JSON.stringify/JSON.parse 扩展 jQuery 实现
    return JSON.stringify(array);
}

$.json2array = function(array) {
    // $.parseJSON(array); // 3.0 开始,已过时
    return JSON.parse(array);
}

// 调用
var json = $.array2json(['a', 'b', 'c']);
var array = $.json2array(json);

11、jQuery 一个对象可以同时绑定多个事件,这是如何实现的?

1
2
3
4
5
6
7
$("#btn").on("mouseover mouseout", func);

$("#btn").on({
    mouseover: func1,
    mouseout: func2,
    click: func3
});

12、针对 jQuery 的优化方法?

  1. 缓存频繁操作DOM对象
  2. 尽量使用id选择器代替class选择器
  3. 总是从#id选择器来继承
  4. 尽量使用链式操作
  5. 使用时间委托 on绑定事件
  6. 采用jQuery的内部函数data()来存储数据
  7. 使用最新版本的 jQuery

13、jQuery 的 slideUp 动画,当鼠标快速连续触发, 动画会滞后反复执行,该如何处理呢?

  1. 在触发元素上的事件设置为延迟处理:使用 JS 原生 setTimeout 方法
  2. 在触发元素的事件时预先停止所有的动画,再执行相应的动画事件:$(’.tab’).stop().slideUp();

14、jQuery UI 如何自定义组件?

  1. 通过向 $.widget() 传递组件名称和一个原型对象来完成
  2. $.widget(“ns.widgetName”, [baseWidget], widgetPrototype);

15、jQuery 与 jQuery UI、jQuery Mobile 区别?

  1. jQuery 是 JS 库,兼容各种PC浏览器,主要用作更方便地处理 DOM、事件、动画、AJAX
  2. jQuery UI 是建立在 jQuery 库上的一组用户界面交互、特效、小部件及主题
  3. jQuery Mobile 以 jQuery 为基础,用于创建“移动Web应用”的框架

16、jQuery 和 Zepto 的区别? 各自的使用场景?

  1. jQuery 主要目标是PC的网页中,兼容全部主流浏览器。在移动设备方面,单独推出 `jQuery Mobile
  2. Zepto从一开始就定位移动设备,相对更轻量级。它的API 基本兼容jQuery`,但对PC浏览器兼容不理想

17、jQuery对象的特点

  1. 只有 JQuery对象才能使用 JQuery 方法
  2. JQuery 对象是一个数组对象

18.你觉得jQuery源码有哪些写的好的地方

  1. jquery源码封装在一个匿名函数的自执行环境中,有助于防止变量的全局污染,
    然后通过传入window对象参数,可以使window对象作为局部变量使用,
    好处是当jquery中访问window对象的时候,就不用将作用域链退回到顶层作用域了,
    从而可以更快的访问window对象。同样,传入undefined参数,可以缩短查找undefined时的作用域链
  2. jquery将一些原型属性和方法封装在了jquery.prototype中,为了缩短名称,又赋值给了jquery.fn,这是很形象的写法
  3. 有一些数组或对象的方法经常能使用到,jQuery将其保存为局部变量以提高访问速度
  4. jquery实现的链式调用可以节约代码,所返回的都是同一个对象,可以提高代码效率

19. 写一个通用的事件侦听器函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// event(事件)工具集,来源:github.com/markyun
markyun.Event = {
    // 视能力分别使用dom0||dom2||IE方式 来绑定事件
    // 参数: 操作的元素,事件名称 ,事件处理程序
    addEvent : function(element, type, handler) {
        if (element.addEventListener) {
            //事件类型、需要执行的函数、是否捕捉
            element.addEventListener(type, handler, false);
        } else if (element.attachEvent) {
            element.attachEvent('on' + type, function() {
                handler.call(element);
            });
        } else {
            element['on' + type] = handler;
        }
    },
    // 移除事件
    removeEvent : function(element, type, handler) {
        if (element.removeEventListener) {
            element.removeEventListener(type, handler, false);
        } else if (element.datachEvent) {
            element.detachEvent('on' + type, handler);
        } else {
            element['on' + type] = null;
        }
    },
    // 阻止事件 (主要是事件冒泡,因为IE不支持事件捕获)
    stopPropagation : function(ev) {
        if (ev.stopPropagation) {
            ev.stopPropagation();
        } else {
            ev.cancelBubble = true;
        }
    },
    // 取消事件的默认行为
    preventDefault : function(event) {
        if (event.preventDefault) {
            event.preventDefault();
        } else {
            event.returnValue = false;
        }
    },
    // 获取事件目标
    getTarget : function(event) {
        return event.target || event.srcElement;
    }
}

20、如何判断一个对象是否为数组

1
2
3
4
5
6
function isArray(arg) {
    if (typeof arg === 'object') {
        return Object.prototype.toString.call(arg) === '[object Array]';
    }
    return false;
}

21、冒泡排序

每次比较相邻的两个数,如果后一个比前一个小,换位置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
var arr = [3, 1, 4, 6, 5, 7, 2];
function bubbleSort(arr) {
    for (var i = 0; i < arr.length - 1; i++) {
        for(var j = 0; j < arr.length - i - 1; j++) {
            if(arr[j + 1] < arr[j]) {
                var temp;
                temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
    return arr;
}
console.log(bubbleSort(arr));

22、快速排序

采用二分法,取出中间数,数组每次和中间数比较,小的放到左边,大的放到右边

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
var arr = [3, 1, 4, 6, 5, 7, 2];
function quickSort(arr) {
    if(arr.length == 0) {
        return [];    // 返回空数组
    }
    var cIndex = Math.floor(arr.length / 2);
    var c = arr.splice(cIndex, 1);
    var l = [];
    var r = [];

    for (var i = 0; i < arr.length; i++) {
        if(arr[i] < c) {
            l.push(arr[i]);
        } else {
            r.push(arr[i]);
        }
    }
    return quickSort(l).concat(c, quickSort(r));
}

console.log(quickSort(arr));

23、编写一个方法 求一个字符串的字节长度

假设:一个英文字符占用一个字节,一个中文字符占用两个字节

1
2
3
4
5
6
7
8
9
function GetBytes(str){
    var len = str.length;
    var bytes = len;
    for(var i=0; i<len; i++){
        if (str.charCodeAt(i) > 255) bytes++;
    }
    return bytes;
}
console.log(GetBytes("你好,as"));

24、bind的用法,以及如何实现bind的函数和需要注意的点

bind的作用与call和apply相同,
区别是call和apply是立即调用函数,而bind是返回了一个函数,需要调用的时候再执行。
一个简单的bind函数实现如下

1
2
3
4
5
6
Function.prototype.bind = function(ctx) {
    var fn = this;
    return function() {
        fn.apply(ctx, arguments);
    };
};

25.谈谈你对重构的理解

  1. 网站重构:在不改变外部行为的前提下,简化结构、添加可读性,而在网站前端保持一致的行为。也就是说是在不改变UI的情况下,对网站进行优化, 在扩展的同时保持一致的UI
  2. 对于传统的网站来说重构通常是:
    • 表格(table)布局改为DIV+CSS
    • 使网站前端兼容于现代浏览器(针对于不合规范的CSS、如对IE6有效的)
    • 对于移动平台的优化
    • 针对于SEO进行优化

26.什么样的前端代码是好的

  1. 高复用低耦合,这样文件小,好维护,而且好扩展。

27.对前端工程师这个职位是怎么样理解的?它的前景会怎么样?

  1. 前端是最贴近用户的程序员,比后端、数据库、产品经理、运营、安全都近
    • 实现界面交互
    • 提升用户体验
    • 有了Node.js,前端可以实现服务端的一些事情
  2. 前端是最贴近用户的程序员,前端的能力就是能让产品从 90分进化到 100 分,甚至更好,
  3. 与团队成员,UI设计,产品经理的沟通;
  4. 做好的页面结构,页面重构和用户体验;

28、你觉得前端工程的价值体现在哪

  1. 为简化用户使用提供技术支持(交互部分)
  2. 为多个浏览器兼容性提供支持
  3. 为提高用户浏览速度(浏览器性能)提供支持
  4. 为跨平台或者其他基于webkit或其他渲染引擎的应用提供支持
  5. 为展示数据提供支持(数据接口)

29、平时如何管理你的项目?

  1. 先期团队必须确定好全局样式(globe.css),编码模式(utf-8) 等;
  2. 编写习惯必须一致(例如都是采用继承式的写法,单样式都写成一行);
  3. 标注样式编写人,各模块都及时标注(标注关键样式调用的地方);
  4. 页面进行标注(例如 页面 模块 开始和结束);
  5. CSS跟HTML 分文件夹并行存放,命名都得统一(例如style.css);
  6. JS 分文件夹存放 命名以该JS功能为准的英文翻译。
  7. 图片采用整合的 images.png png8 格式文件使用 - 尽量整合在一起使用方便将来的管理

转发来源链接