0-0.常用的四种设计模式
1.工厂模式:解决多个相似的问题;
2.单例模式:只能被实例化一次;
3.沙箱模式:自执行函数,使用闭包把内部方法暴露出来,例:
var fn=(function(){
function aFn(){};
return {
aFn:aFn
}
})
4.发布者订阅模式:有新消息主动推送的功能模式;
0-1.编程范式
1.命令式编程(流水式从上至下执行)
2.面向编程(函数式编程:闭包(函数组合嵌套的方式),一类函数,箭头函数)
3.面向对象式编程(OOP:原型(链式的链接对象的对象)继承(存在父子间属性函数的使用))
优缺点: 对象函数属性排列易于理解;命令式编码风格计算机能直接快速编译;
多实例时乱象丛生,容易修改原始值导致解析不理想化(缺点)
4.函数式编程:
优缺点: 避免面向对象编程的缺点,自我执行理想化程度高;
复用性良好,存在参数无参数状态,且可以高效完成算法;
执行逻辑清晰,方便修改和优化更新;
避免多线程冲突,逻辑混乱
简洁度很好,易读性稍差(缺点)
0-2.写JavaScript的基本规范?
不要在同一行声明多个变量。
请使用 ===/!==来比较true/false或者数值
使用对象字面量替代new Array这种形式
不要使用全局函数。
Switch语句必须带有default分支
函数不应该有时候有返回值,有时候没有返回值。
for循环必须使用大括号
if语句必须使用大括号
for-in循环中的变量 应该使用var关键字明确限定作用域,从而避免作用域污染。
1.模拟字符串去的hash值
function hashCode(str){
var h = 0, off = 0; var len = str.length;
for(var i = 0; i < len; i++){
h = 31 * h + str.charCodeAt(off++);
}
var t=-2147483648*2;
if(h>2147483647){
h+=t
}
return h;
}
2.获取本地时间的时间戳
var timestamp=Date.parse(new Date()); //特殊存在:毫秒显示为000(不去秒以下的数值)
var timestamp=(new Date()).valueOf();
var timestamp=new Date().getTime();
3.fixed固定定位不随滚动条移动
<div class=”fixedDiv”>…</div>
.fixedDiv{
position:fixed;
width:1000px;
bottom:0;
z-index:1000;
}
window.onscroll=function(){
var sl=Math.max(document.body.scrollLeft,document.documentElement.scrollLeft);
document.getElementsByClassName(“fixedDiv”)[0].style.left=(-sl)+”px”;
}
4.获取指定字符串中某字符出现的所有下标
function getAllIndex(str,chars){
var arr=[];
for(var i=0;i<str.length;i++){
if(str.substring(i,i+1)==chars){
arr.push(i)
}
}
return arr
}
5.监听滚动条的事件,并获取top&bottom的距离
$(window).scroll(function() {
var scrollTop = $(this).scrollTop();
var docHeight = $(document).height();
var windowHeight = $(this).height();
var scrollHeight=document.body.scrollHeight;
console.log("scrollTop:"+scrollTop);
console.log("scrollbottom:"+(docHeight-scrollTop-windowHeight));
if(scrollTop + windowHeight == docHeight) {
alert("已经到最底部了!");
}
});
6.-‘类继承’和‘原型继承’有什么区别?
类继承:
实例由类继承而来(建筑图纸和实际建筑的关系),同时还会创建父类—子类这样一种关系,也叫做类的分层
分类。通常是用 new 关键字调用类的构造函数来创建实例的。不过在 ES6 中,要继承 一个类,不用 class 关
键字也可以。尽量不用类继承,除非是单一级的使用。
原型继承:
实例/对象直接从其它对象继承而来,创建实例的话,往往用工厂函数或者 Object.create() 方法。实例可
以从多个不同的对象组合而来,这样就能选择性地继承了。主要实现手段有:委托(原型链);组合;函数式(这
个函数式原型继承不是函数式编程。这里的函数是用来创建一个闭包,以实现私有状态或者封装)
7.双向数据绑定/单向数据流的含义和区别
双向数据绑定:
UI 层所呈现的内容和 Model 层的数据动态地绑定在一起,其中一个发生了变化,就会立刻反映在另一个
上。比如用户在前端页面的表单控件中输入了一个值,Model 层对应该控件的变量就会立刻更新为用户所输入的
值;反之亦然,如果 Modal 层的数据有变化,变化后的数据也会立刻反映至 UI 层。Angular 则是双向数据绑
定的典型。
单向数据流:
意味着只有 Model 层才是单一数据源。UI 层的变化会触发对应的消息机制,告知 Model 层用户的目的。
只有 Model 层才有更改应用状态的权限,这样一来,数据永远都是单向流动的,其状态的变化是很容易跟踪的。
React 是单向数据流的典型。
8.jquery不常用但实用的方法
(1)位置相关
offset() $(“#qq”).offset() 相对浏览器窗口的位置
offsetParent() $(“#qq”).offsetParent() #qq相对最近的已经定位的祖先的位置
position() $(“#qq”).position() 已定位的元素的position值
(2)DOM元素的包裹
wrap() $(“#qq”).wrap(“<div id=’qqPar’/>”)
wrapAll() 所有指定元素都会被包裹
wrapInner() 指定元素的内容会被包裹
(3)删除相关
detach() 删除了还能恢复
empty() 删除子元素的所有东西
remove() 删除指定元素
unwrap() 删除指定元素的父节点,但是保留本身
9.基本类型与引用类型有什么区别?
基本数据类型: Undefined、Null、Boolean、Number、String
引用数据类型: Object, Array, Date, RegExp(正则), Function
区别:
存储:
基本类型值在内存中占据固定大小的空间,因此被保存在栈内存中
引用类型的值是对象, 保存在堆内存中. 引用类型的变量实际上是一个指向该对象的指针
复制:
从一个变量向另一个变量复制基本类型的值, 会创建这个值的一个副本
从一个变量向另一个变量复制引用类型的值, 复制的其实是指针, 因此两个变量最终都指向同一个对象
检测:
确定一个值是哪种基本类型可以用typeof操作符
确定一个值是哪种引用类型可以使用instanceof操作符
10.null,undefined 的区别?
undefined 表示不存在这个值 typeof undefined //"undefined"
null 一个对象被定义了,值为“空值” typeof null //"object"
undefined :是一个表示"无"的原始值或者说表示"缺少值",就是此处应该有一个值,但是还没有定义。例如变量
被声明了,但没有赋值时,就等于undefined
null :是一个空对象, 没有任何属性和方法。例如作为函数的参数,表示该函数的参数不是对象
注意:在验证null时,一定要使用 === ,因为 == 无法分别 null 和 undefined
11.什么是闭包(closure),为什么要用它?
闭包:是指有权访问另一个函数作用域中变量的函数。
特点:
1.创建闭包的最常见的方式就是在一个函数内创建另一个函数;
2.利用闭包可以突破作用链域,将函数内部的变量和方法传递到外部;
3.使用闭包主要是为了设计私有的方法和变量;
4.闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量;
5.在js中,函数即闭包,只有函数才会产生作用域的概念;
特征:
1.函数内再嵌套函数;
2.内部函数可以引用外层的参数和变量;
3.参数和变量不会被垃圾回收机制回收;
例子:
var add = (function () {
var counter = 0;
return function () {return counter += 1;}
})();
add();
//1
add();
//2
12.什么是伪数组
伪数组概念:是能通过Array.prototype.slice 转换为真正的数组的带有length属性的对象;
伪数组示例:
1.arguments对象
2.调用getElementsByTagName,document.childNodes之类的node集合
伪数组变更:
Array.prototype.slice.call(fakeArray)转变为真正的Array对象,返回新数组而不会修改原数组
13.javascript创建对象的几种方式
1.对象字面量(最后一个key-value不添加逗号)
var obj={
name:"yjs",
age:25,
};
优缺点:复用性较差(缺)
2.构造函数(函数名首字母使用大写,区分函数和自定义对象,可以传参的呦)
function NewObj(){}
var person=new NewObj();
person.name="yjs";
person.age="25";
person.city="sjz";
person.getName=function(){
console.log("对象的名称是:"+person.name)
}
person.getName();
优缺点:复用性较差(缺)
3.构造函数-含参(用this关键字定义构造的上下文属性,一般不会出现return的语句)
function One(name,age,city){
this.name=name;
this.age=age;
this.city=city;
this.getName=function(){
console.log("对象的名称是:"+person.name)
}
}
var one=new One("yjs",25,"sjz");//实例化对象
one.getName();
优缺点:实例化的对象可以识别指定的类型(优);每次实例都会重新创建函数,全局变量多(缺)
4.工厂函数(内置对象,这种事最不推荐使用的)
var per=new Object();
per.name="yjs";
per.age=25;
per.city="sjz";
per.getName=function(){
console.log("对象的名称是:"+person.name)
}
per.getName();
优缺点:所有的实例都指向一个原型,对象无法识别(缺)
5.原型
function One(){}
One.prototype.name="yjs";
One.prototype.getName=function(){
console.log("对象的名称是:"+person.name)
}
var one=new One();
one.getName();
优缺点:创建函数放在原型避免全局变量多的问题(优);不能初始化参数(缺)
6.混合(举例为:构造函数方式和原型方式的混合,以上几种可任意组合)
function One(name){
this.name=name;
}
One.prototype.getName=function(){
console.log("对象的名称是:"+person.name)
}
var one=new One("yjs");
one.getName();
14.谈谈This对象的理解。
1.this总是指向函数的直接调用者(而非间接调用者);
2.如果有new关键字,this指向new出来的那个对象;
3.事件中,this指向触发这个事件的对象(特殊:IE中的attachEvent中的this总是指向全局对象Window);
15.call()和apply()方法的区别
作用:都能继承另一个对象的方法和属性
区别:参数列表不一样
书写:Function.call(obj, arg1, arg2,...) Function.apply(obj, args)
参数:obj-要被继承的对象;第二个参数-传递的实参值
举例:
function A(a){console.log(a)}
function B(b,c){console.log(b+c)}
A.call(B,10); //10
B.applay(A,[10,20]) //30
16.new操作符具体干了什么
1.创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型。
var obj = {};
2.属性和方法被加入到 this 引用的对象中。
obj.__proto__ = Base.prototype;
3.新创建的对象由 this 所引用,并且最后隐式的返回 this 。
Base.call(obj);
17.IE与火狐的事件机制有什么区别? 如何阻止冒泡
事件:网页中的某个操作,点击,悬停,双击,键盘事件等
机制:IE是事件冒泡、其他的浏览器同时支持两种事件模型(捕获型事件和冒泡型事件)
阻止:ev.stopPropagation();(旧ie的方法 ev.cancelBubble = true;)
18.事件委托(事件代理)是什么
原理:事件冒泡, 委托到已知的父级元素。
范围:1.js脚本动态添加的;2.不好定位的元素事件;3.相同元素过多;
例子:
html部分:
<ul id="list">
<li id="li-1">Li 2</li>
<li id="li-2">Li 3</li>
</ul>
js部分:
document.getElementById("list").addHandler("click", function(e){
var e = e || window.event;
var target = e.target || e.srcElement;
if(target.nodeName.toUpperCase == "LI"){
console.log("li的ID是:"+e,target.id);
}
});
19.XML和JSON的区别
1.JSON相对于XML来讲,数据的体积小,传递的速度更快;
2.JSON与JavaScript的交互更加方便,更容易解析处理,更好的数据交互;
3.JSON对数据的描述性比XML较差;
4.JSON的速度要远远快于XML;
20.哪些操作会造成内存泄漏
1.setTimeout 的第一个参数使用字符串而非函数的话,会引发内存泄漏;
2.闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环);
3.当页面中元素被移除或替换时,若元素绑定的事件仍没被移除,在IE中不会作出恰当处理,此时要先手工移除事件,不然会存在内存泄露。
21.面向对象中继承实现
1.prototype原型链方式:
function One(name){
this.name = name;
this.getName=function(){
console.log(this.name);
}
}
function Two(name){
this.name = name;
}
Two.prototype = new One();
var a = new One("gc");
var b = new Two("yjs");
a.getName(); //gc
b.getName(); //yjs
2、call()/apply()方法
function One(name){
this.name = name;
this.getName=function(){
console.log(this.name);
}
}
function Two(){
var args = arguments;
One.call(this,args[0]); // One.apply(this,arguments);
}
var a = new One("gc");
var b = new Two("yjs");
a.getName(); //gc
b.getName(); //yjs
3.混合方法(prototype,call/apply)
function One(name){
this.name = name;
this.getName=function(){
console.log(this.name);
}
}
function Two(){
var args = arguments;
One.call(this,args[0]);
}
Two.prototype = new One();
var b = new Two("yjs");
b.getName(); //yjs
4.对象冒充
function One(name){
this.name = name;
this.getName=function(){
console.log(this.name);
}
}
function Two(name){
this.tt = One; //将One类的构造函数赋值给this.tt
this.tt(name); //js中实际上是通过对象冒充来实现继承的
delete this.tt; //移除对One的引用
}
var a = new One("gc");
var b = new Two("yjs");
a.getName(); //gc
b.getName(); //yjs
22.