专业编程教程与实战项目分享平台

网站首页 > 技术文章 正文

刷前端面经笔记(1) 前端刷题

ins518 2024-10-04 01:51:14 技术文章 11 ℃ 0 评论

1.apply,call,bind有什么区别?

三者都可以把一个函数应用到其他对象上, apply , call 是直接执行函数调用, bind 是绑定,执行需要再次调用。

apply 和 call 的区别是 apply 接受数组作为参数,而 call 是接受逗号分隔的无限多个参数列表。

代码如下:

	function Person() {
 }
 Person.prototype.sayName() { alert(this.name); }

 var obj = {name: 'michaelqin'}; // 注意这是一个普通对象,它不是Person的实例
 // 1) apply
 Person.prototype.sayName.apply(obj, [param1, param2, param3]);

 // 2) call
 Person.prototype.sayName.call(obj, param1, param2, param3);

 // 3) bind
 var liaoke = Person.prototype.sayName.bind(obj); 
 liaoke ([param1, param2, param3]); // bind需要先绑定,再执行 
 liaoke (param1, param2, param3); // bind需要先绑定,再执行

2.介绍一下defineProperty,hasOwnProperty,isEnumerable

Object.defineProperty(obj,prop,descriptor) 用来给对象定义属性,有 value ,writeable , enumerable , set/get , configurable ,

hasOwnProperty 用于检查某一属性是不是存在于对象本身,

isEnumerable 用来检测某一属性是否可遍历,也就是能不能用 for...in 循环来取到。

3.JS常用设计模式的实现思路(单例、工厂、代理、装饰、观察者模式等)

	// 1) 单例: 任意对象都是单例,无须特别处理
 var obj = {name: 'michaelqin', age: 30};

 // 2) 工厂: 就是同样形式参数返回不同的实例
 function Person() { this.name = 'Person1'; }
 function Animal() { this.name = 'Animal1'; }

 function Factory() {}
 Factory.prototype.getInstance = function(className) {
 return eval('new ' + className + '()');
 }

 var factory = new Factory();
 var obj1 = factory.getInstance('Person');
 var obj2 = factory.getInstance('Animal');
 console.log(obj1.name); // Person1
 console.log(obj2.name); // Animal1

 // 3) 代理: 就是新建个类调用老类的接口,包一下
 function Person() { }
 Person.prototype.sayName = function() { console.log('michaelqin'); }
 Person.prototype.sayAge = function() { console.log(30); }

 function PersonProxy() { 
 this.person = new Person();
 var that = this;
 this.callMethod = function(functionName) {
 console.log('before proxy:', functionName);
 that.person[functionName](); // 代理
 console.log('after proxy:', functionName);
 }
 }

 var pp = new PersonProxy();
 pp.callMethod('sayName'); // 代理调用Person的方法sayName()
 pp.callMethod('sayAge'); // 代理调用Person的方法sayAge() 

 // 4) 观察者: 就是事件模式,比如按钮的onclick这样的应用.
 function Publisher() {
 this.listeners = [];
 }
 Publisher.prototype = {
 'addListener': function(listener) {
 this.listeners.push(listener);
 },

 'removeListener': function(listener) {
 delete this.listeners[listener];
 },

 'notify': function(obj) {
 for(var i = 0; i < this.listeners.length; i++) {
 var listener = this.listeners[i];
 if (typeof listener !== 'undefined') {
 listener.process(obj);
 }
 }
 }
 }; // 发布者

 function Subscriber() {

 }
 Subscriber.prototype = {
 'process': function(obj) {
 console.log(obj);
 }
 }; // 订阅者

 var publisher = new Publisher();
 publisher.addListener(new Subscriber());
 publisher.addListener(new Subscriber());
 publisher.notify({name: 'michaelqin', ageo: 30}); // 发布一个对象到所有订阅者
 publisher.notify('2 subscribers will both perform process'); // 发布一个字符串到所有订阅者

3.处理字符串常用的十个函数

	charAt() // 返回在指定位置的字符。
concat() // 连接字符串。
fromCharCode() // 从字符编码创建一个字符串。
indexOf() // 检索字符串。
match() // 找到一个或多个正则表达式的匹配。
replace() // 替换与正则表达式匹配的子串。
search() // 检索与正则表达式相匹配的值。
slice() // 提取字符串的片断,并在新的字符串中返回被提取的部分。
split() // 把字符串分割为字符串数组。
substr() // 从起始索引号提取字符串中指定数目的字符。
substring() // 提取字符串中两个指定的索引号之间的字符。
toLocaleLowerCase() // 把字符串转换为小写。
toLocaleUpperCase() // 把字符串转换为大写。
toLowerCase() // 把字符串转换为小写。
toUpperCase() // 把字符串转换为大写。
toString() // 返回字符串。
valueOf() // 返回某个字符串对象的原始值。

4.如何判断一个变量是对象还是数组

	function isObjArr(variable){
 if (Object.prototype.toString.call(value) === "[object Array]") {
 console.log('value是数组');
 }else if(Object.prototype.toString.call(value)==='[object Object]'){//这个方法兼容性好一点
 console.log('value是对象');
 }else{
 console.log('value不是数组也不是对象')
 }
}

// 注意:千万不能使用typeof来判断对象和数组,因为这两种类型都会返回"object"。

5.ES5的继承和ES6的继承有什么区别?

ES5 的继承是通过 prototype 或构造函数机制来实现。

ES5 的继承实质上是先创建子类的实例对象,然后再将父类的方法添加到 this 上(Parent.apply(this) )。

ES6 的继承机制实质上是先创建父类的实例对象 this (所以必须先调用父类的 super() 方法),然后再用子类的构造函数修改 this 。具体为 ES6 通过 class 关键字定义类,里面有构造方法,类之间通过 extends 关键字实现继承。子类必须在 constructor 方法中调用 super方法,否则新建实例报错。因为子类没有自己的 this 对象,而是继承了父类的 this 对象,然后对其调用。如果不调用 super 方法,子类得不到 this 对象。

注意:super关键字指代父类的实例,即父类的this对象。在子类构造函数中,调用super后,才可使用this关键字,否则报错。

6.下面的ul,如何点击每一列的时候alert其index?(闭包)

	<ul id="test">
 <li>这是第一条</li>
 <li>这是第二条</li>
 <li>这是第三条</li>
 </ul>


// 方法一:
var lis=document.getElementById('test').getElementsByTagName('li');
for(var i=0;i<3;i++)
{
lis[i].index=i;
lis[i].onclick=function(){
alert(this.index);
};
}

//方法二:
var lis=document.getElementById('test').getElementsByTagName('li');
for(var i=0;i<3;i++)
{
lis[i].index=i;
lis[i].onclick=(function(a){
return function() {
alert(a);
}
})(i);
}

7.对于MVVM的理解

MVVM 是 Model-View-ViewModel 的缩写。

Model 代表数据模型,也可以在 Model 中定义数据修改和操作的业务逻辑。

View 代表 UI 组件,它负责将数据模型转化成 UI 展现出来。

ViewModel 监听模型数据的改变和控制视图行为、处理用户交互,

简单理解就是一个同步 View 和 Model 的对象,连接 Model 和 View 。

在 MVVM 架构下, View 和 Model 之间并没有直接的联系,

而是通过 ViewModel 进行交互, Model 和 ViewModel 之间的交互是双向的,

因此 View 数据的变化会同步到 Model 中,而 Model 数据的变化也会立即反应到 View 上。

ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,

而 View 和 Model 之间的同步工作完全是自动的,无需人为干涉,

因此开发者只需关注业务逻辑,不需要手动操作 DOM ,

不需要关注数据状态的同步问题,

复杂的数据状态维护完全由 MVVM 来统一管理。

8.解释Vue的生命周期

Vue 实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom->渲染、更新->渲染、销毁等一系列过程,称之为 Vue 的生命周期。

Vue 的生命周期包括:

beforeCreate (创建前)在数据观测和初始化事件还未开始,

created (创建后)完成数据观测,属性和方法的运算,初始化事件, $el 属性还没有显示出来;

beforeMount( 载入前)在挂载开始之前被调用,相关的 render 函数首次被调用,实例已完成以下的配置:编译模板,把 data 里面的数据和模板生成 html ,注意此时还没有挂载html 到页面上;

mounted (载入后)在 el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用,实例已完成以下配置:用上面编译好的 html 内容替换 el 属性指向的 DOM 对象,完成模板中的 html渲染到 html 页面中,此过程中进行 ajax 交互。

beforeUpdate (更新前)在数据更新之前调用,发生在虚拟 DOM 重新渲染和打补丁之前,可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。

updated (更新后)在由于数据更改导致的虚拟 DOM 重新渲染和打补丁之后调用。调用时,组件 DOM 已经更新,所以可以执行依赖于 DOM 的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环,该钩子在服务器渲染期间不被调用。

beforeDestroy (销毁前)在实例销毁之前调用,实例仍然完全可用。

destroyed (销毁后)在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。

9.为什么使用Node.js,它有哪些优缺点?

优点:

事件驱动,通过闭包很容易实现客户端的生命活期。

不用担心多线程,锁,并行计算的问题

V8 引擎速度非常快

对于游戏来说,写一遍游戏逻辑代码,前端后端通用

缺点:

node.js 更新很快,可能会出现版本兼容

node.js 还不算成熟,还没有大制作

node.js 不像其他的服务器,对于不同的链接,不支持进程和线程操作

10.什么是错误优先的回调函数?

错误优先( Error-first )的回调函数( Error-First Callback )用于同时返回错误和数据。

第一个参数返回错误,并且验证它是否出错;其他参数返回数据。

	fs.readFile(filePath, function(err, data)
{
 if (err)
 {
 // 处理错误
 return console.log(err);
 }
 console.log(data);
});

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表