前端面试所遇到的技术点
前端面试所遇到的技术点:
面试问题:
function Person(){ } Person.prototype.name = "bill"; Person.prototype.address = "GuangZhou"; Person.sayName = function (){ alert(this.name); } var person1 = new Person(); var person2 = new Person(); //测试代码 alert(person1.name); // bill alert(person2.name); // bill person1.sayName(); //bill person2.sayName(); //bill person1.name = "666"; alert(person1.name); // 666 alert(person2.name); // bill person1.sayName(); //666 person2.sayName(); //bill
function Person(name, url) { //注意构造函数名第一个字母大写 this.name = name; this.url = url; this.alertUrl = alertUrl; } function alertUrl() { alert(this.url); }
function a(name){ var b = new object(); b.name = name; b.say = function(){ alert(this.name); } return b }
ary.splice(n,m,x)从索引n开始删除m个元素,把新增的元素X放在索引n的前面,把删除的元素当成一个新数组返回,原有数组改变 ary.pop() 删除数组的最后一项,返回的是删除的那一项,原有数组改变 ary.shift() 删除数组的的第一项,返回的是删除的那一项,原有数组改变 ary.push() 向数组末尾添加元素,返回的是添加后新数组的长度,原有数组改变 ary.unshift() 向数组开头添加元素,返回的是添加后新数组的长度,原有数组改 slice(n-1,m)把数组的第n项到第m项提取出来 slice(n) 从索引n开始查找到数组末尾 slice(0) slice() 将原有数组复制一份 属于数组克隆 concat() 也可以实现数组克隆 concat的本意是实现数组的拼接 ary.concat(ary2) 把两个数组进行拼接 reverse() 把数组倒过来排序,原有数组改变 sort 可以实现由大到小或者由小到大的排序 indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。 foreach map
。。Onclick和addEventListener这两种方式监听事件的区别:
1. 增 创建元素节点 :document.createElement(“div”); 创建text节点 :document.createTextNodet(“内容”); 复制一个节点: var newNode = node.cloneNode();//参数为true复制所有子节点,参数为false只执行一次浅复制。 2. 删 removeChild();//该方法不是在待删除的节点上调用,而是在它的父元素节点上调用。 node.parentElement.removeChild(node); replaceChild();//删除一个子节点,并用一个新的节点取代它。第一个参数是新节点,第二个参数是要删除的节点。 node.parentElement.replaceChild(newNode,node); 获取和设置非标准的HTML属性 Element定义了getAttribute和setAttribute方法来查询和设置非标准属性,hasAttribute和removeAttribute来检测命名属性是否存在和完全删除属性。 对内容的修改 innerHTML:包含标签的内容 innerText(火狐支持不好):纯文本的元素内容 textContent(IE不支持):纯文本的元素内容 4. 查 一步查找到位 document.getElementById() 返回对拥有指定 id 的第一个对象的引用。 document. getElementsByClassName() 返回文档中所有指定类名的元素集合。 document.getElementsByName() 返回带有指定名称的对象集合。 document.getElementsByTagName() 返回带有指定标签名的对象集合。 查找父子兄弟 对于一个Node节点,包含很多种,像:Document节点、Text节点、Comment节点、Element节点,我们常常需要获得的是元素节点,忽略掉Text和Comment节点: firstElementChild,lastElementChild; children => 数组类型:children[0] ,第一个子节点 nextElementSibling,previousElementSibling => 兄弟节点 parentElement => 父亲节点 5. 插 Node有方法appendChild()和insertBefore()。 parent.appendChild(child); // 插入到最后 parent.insertBefore(newNode,node);//插入到node之前
4、元素的大小及其相对于视口的位置 getBoundingClientRect() 5、上边偏移量,左边的偏移量 offsetTop offsetLest 6、可视区域的大小 document.documentElement.clientWidth document.documentElement.clientHeight 7、页面的实际大小 document.documentElement.scrollWidth document.documentElement.scrollHeight 10、屏幕可用宽高(去除任务栏) window.screen.availWidth window.screen.availHeight 11、窗口的内高度、内宽度(文档显示区域+滚动条) window.innerWidth window.innerHeight 12、窗口的外高度、外宽度 window.outerWidth window.outerHeiht
Navigator 对象属性:
appCodeName 返回浏览器的代码名。 appMinorVersion 返回浏览器的次级版本。 appName 返回浏览器的名称。 appVersion 返回浏览器的平台和版本信息。 browserLanguage 返回当前浏览器的语言。 cookieEnabled 返回指明浏览器中是否启用 cookie 的布尔值。 cpuClass 返回浏览器系统的 CPU 等级。 onLine 返回指明系统是否处于脱机模式的布尔值。 platform 返回运行浏览器的操作系统平台。 systemLanguage 返回 OS 使用的默认语言。 userAgent 返回由客户机发送服务器的 user-agent 头部的值。 userLanguage 返回 OS 的自然语言设置。
1、window.location.href(设置或获取整个 URL 为字符串)
var test = window.location.href;
alert(test);
返回:http://i.cnblogs.com/EditPosts.aspx?opt=1
2、window.location.protocol(设置或获取 URL 的协议部分)
var test = window.location.protocol;
alert(test);
返回:http:
3、window.location.host(设置或获取 URL 的主机部分)
var test = window.location.host;
alert(test);
返回:i.cnblogs.com
4、window.location.port(设置或获取与 URL 关联的端口号码)
var test = window.location.port;
alert(test);
返回:空字符(如果采用默认的80端口(update:即使添加了:80),那么返回值并不是默认的80而是空字符)
5、window.location.pathname(设置或获取与 URL 的路径部分(就是文件地址))
var test = window.location.pathname;
alert(test);
返回:/EditPosts.aspx
6、window.location.search(设置或获取 href 属性中跟在问号后面的部分)
var test = window.location.search;
alert(test);
返回:?opt=1
PS:获得查询(参数)部分,除了给动态语言赋值以外,我们同样可以给静态页面,并使用javascript来获得相信应的参数值。
7、window.location.hash(设置或获取 href 属性中在井号“#”后面的分段)
var test = window.location.hash;
alert(test);
返回:空字符(因为url中没有)
8、js获取url中的参数值???逻辑判断下来琢磨
用户地理位置的 获取:
获取用户地理位置关键api:
var option = { enableHighAccuracy:true, //设置提升定位的精准度 maximumAge:0, //禁用缓存 timeout:30000 //开始获取定位信息30秒后超时 } if(navigator.geolocation){ //判断是否支持Geolocation API navigator.geolocation.getCurrentPosition(showPosition,showError,option) } function showPosition(position){ var lat = position.coords.latitude; //获取纬度 var lon = position.coords.longitude; //获取经度 alert("您的纬度是:"+lat+ ",经度是:"+lon); } function showError(error){ switch(error.code){ case error.PERMISSION_DENIED: alert("您拒绝了地理定位服务"); break; case error.POSITION_UNAVAILABLE: alert("无法获取您的位置"); break; case error.TIMEOUT: alert("超时"); break; } }
DOM链式调用的处理:
1.节约JS代码.
2.所返回的都是同一个对象,可以提高代码的效率。
//定义一个JS类 function Demo() { } //扩展它的prototype Demo.prototype ={ setName:function (name) { this.name=name; console.log(this) return this; }, getName:function (name) { // return this.name; this.sex=name console.log(this) return this }, setAge:function (age) { this.age=age; console.log(this) return this; } }; ////工厂函数 function D() { return new Demo(); } //去实现可链式的调用 D().setName("CJ").setAge(18).setName();
$("p").show() //显示隐藏的匹配元素 $("p").show("slow"); //参数表示速度,("slow","normal","fast"),也可为900毫秒 $("p").hide() //隐藏显示的元素 $("p").toggle(); //切换 显示/隐藏
页面载入
当页面载入成功后再运行的函数事件 $(document).ready(function(){ do something... }); //简写 $(function($) { do something... });
Virual DOM是用JS对象记录一个dom节点的副本,当dom发生更改时候,先用
虚拟dom进行diff,算出最小差异,然后再修改真实dom。
vue的virtual dom的diff算法是基于snabbdom算法改造而来,与react的diff算法一样
仅在同级的vnode间做diff,递归的进行同级vnode的diff,最终实现整个DOM树的更新。
虚拟DOM的缺点:
1. 代码更多,体积更大
2. 内存占用增大
3. 小量的单一的dom修改使用虚拟dom成本反而更高,不如直接修改真实dom快,所以一般简单的页面制作可以直接用jQuery,而不用框架
更新视图但不重新请求页面,是前端路由原理的核心之一,目前在浏览器环境中这一功能的实现主要有2
种方式:
- 利用
URL
中的hash
("#"
); - 利用
History interface
在HTML5
中新增的方法;
- 每一次改变
hash
(window.location.hash
),都会在浏览器访问历史中增加一个记录。
利用hash
的以上特点,就可以来实现前端路由"更新视图但不重新请求页面"的功能了。
HashHistory
hash
("#"
)符号的本来作用是加在URL
指示网页中的位置:
http://www.example.com/index.html#print
#
本身以及它后面的字符称之为hash
可通过window.location.hash
属性读取.
hash
虽然出现在url
中,但不会被包括在http
请求中,它是用来指导浏览器动作的,对服务器端完全无用,因此,改变hash
不会重新加载页面。- 可以为
hash
的改变添加监听事件:
window.addEventListener("hashchange",funcRef,false)
- 每一次改变
hash
(window.location.hash
),都会在浏览器访问历史中增加一个记录。
利用hash
的以上特点,就可以来实现前端路由"更新视图但不重新请求页面"的功能了。
transitionTo()
方法是父类中定义的是用来处理路由变化中的基础逻辑的,push()
方法最主要的是对window
的hash
进行了直接赋值:window.location.hash=route.fullPath
HashHistory.replace():
replace()方法与push()方法不同之处在于,它并不是将新路由添加到浏览器访问历史栈顶,而是替换掉当前的路由:
HTML5History
History interface
是浏览器历史记录栈提供的接口,通过back()
,forward()
,go()
等方法,我们可以读取浏览器历史记录栈的信息,进行各种跳转操作。
从HTML5
开始,History interface
提供了2个新的方法:pushState()
,replaceState()
使得我们可以对浏览器历史记录栈进行修改:
window.history.pushState(stateObject,title,url)
window.history,replaceState(stateObject,title,url)
stateObject
:当浏览器跳转到新的状态时,将触发popState
事件,该事件将携带这个stateObject
参数的副本title
:所添加记录的标题url
:所添加记录的url
这2
个方法有个共同的特点:当调用他们修改浏览器历史栈后,虽然当前url
改变了,但浏览器不会立即发送请求该url
,这就为单页应用前端路由,更新视图但不重新请求页面提供了基础。
一般的需求场景中,hash
模式与history
模式是差不多的,根据MDN
的介绍,调用history.pushState()
相比于直接修改hash
主要有以下优势:
pushState
设置的新url
可以是与当前url
同源的任意url
,而hash
只可修改#
后面的部分,故只可设置与当前同文档的url
pushState
设置的新url
可以与当前url
一模一样,这样也会把记录添加到栈中,而hash
设置的新值必须与原来不一样才会触发记录添加到栈中pushState
通过stateObject
可以添加任意类型的数据记录中,而hash
只可添加短字符串pushState
可额外设置title
属性供后续使用
理解什么是状态管理模式?
状态管理:简单的理解就是统一管理和维护各个vue组件的可变化状态。
我们明白vue是单向数据流的,那么它的状态管理一般包含如下几部分:
1. state; 驱动应用的数据(一般指data中返回的数据)。
2. view; 一般指模板,以声明的方式将state的数据映射到视图。
3. actions: 响应在view上的用户输入导致的状态变化。
但是当我们的应用遇到多个组件共享状态时候,那么单向数据流可能不太满足我们的需求:
比如如下几个方面:
1. 多个视图依赖于同一状态。
传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。
2. 我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。
因此我们可以把组件的共享状态提取出来,作为全局来管理,因此vuex产生了。
vuex的优点:
最主要解决了组件之间共享同一状态的问题。可以把组件的共享状态提取出来,作为全局来管理。
什么情况下我应该使用 Vuex?
如果不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,最好不要使用 Vuex。一个简单的 global event bus 就足够您所需了。但是,如果您需要构建是一个中大型单页应用,很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。
二: Vuex状态管理的demo学习
每一个Vuex应用的核心就是store(仓库), store是保存应用中大部分的状态。
Vuex 和一般的全局对象有以下几点不同:
1. Vuex的状态存储是响应性的。
当vue组件从store中读取状态的时候,若store中的状态发生变化,那么相对应的组件也就会得到相应的更新。
2. 我们不能直接修改store中的状态。
改变store中的状态的唯一途径是显示地提交(commit)mutations.
2-1 单一状态树
Vuex使用的是单一状态树,用一个对象就包含了全部的应用层级状态。这也意味着每个应用将仅仅包含一个store的实列。
Vuex的状态存储是响应性的,因此从store实列中读取一个状态的最简单的方法是在计算属性返回某个状态。
-
本地缓存
-
通过key的形式添加缓存setStorage (异步接口)
wx.setStorage({ key:"key" data:"value" })
-
通过key的形式获取缓存getStorage (异步接口)
wx.getStorage({ key: 'key', success: function(res) { console.log(res.data) } })
-
从本地缓存中异步移除指定 key
wx.removeStorage({ key: 'key', success: function(res) { console.log(res.data) } })
-
清理本地数据缓存
wx.clearStorage()
获取用户信息,需要先调用wx.login 接口
wx.getUserInfo({ success: function(res) { var userInfo = res.userInfo var nickName = userInfo.nickName var avatarUrl = userInfo.avatarUrl var gender = userInfo.gender //性别 0:未知、1:男、2:女 var province = userInfo.province var city = userInfo.city var country = userInfo.country } })
-
拨打电话
wx.makePhoneCall({
phoneNumber: '1340000' //仅为示例,并非真实的电话号码
}