Open FrankKai opened 6 years ago
1.说一下你熟悉的设计模式 我最熟悉的设计模式:工厂模式(ES5),组件设计模式(ES6) 工厂模式(ES5,基于prototype。此例中基类Base,子类Factory)
var Factory = function () {
if(!(this instanceof Factory)){
return new Factory();
}
}
Factory.prototype = Object.assign(new Base(), {
version: '0.0.1',
defaultOption:{
title:'标题'
},
init:function (cfg) {
this.title = cfg.title || '';
this.currentOption = Object.assign(this.defaultOption,{
//...
})
},
render: function () {
var option = this.currentOption;
this.chart.setOption(option);
},
showTitle: function () {
this._showTitle();
}
})
组件设计模式(ES6,基于class,方便继承和初始化,也是React组件的推荐写法,我比较喜欢。此例中父类Compnent,子类Retrive)
class Retrive extends Component {
constructor (props) {
super(props);
this.state = {
name:''
};
this.getRemoteData = this.getRemoteData.bind(this);
}
getRemoteData (data) {
this.state.retriveResult = data;
}
render(){
return (
<div className="Retrive">
<Button name="search" onClick={this.getRemoteData}>查询</Button>
</div>
);
}
}
2.说一下你理解的模块机制 AMD: 异步模块加载规范。 a.js,定义一个依赖jQuery和echrts的组件。
define(['jquery', 'echarts'], function ($, echarts) {
var AMD = function(){}
AMD.prototype = {
title:'',
foo: function(){}//AMD类或者继承AMD类的子类的属性
}
function bar(){}//返回,公共属性
function baz(){} //未返回,私有属性
return {
main:AMD,
bar: bar
}
});
如果b.js依赖a.js,可以这样
define(['./a'], function (a) {
//调用构造函数,foo
var instance_amd = new a.main();
instance_amd.foo()
//调用bar
a.bar()
});
ES6 modules: 和python的包机制很类似,导入import,导出export。
1.场景:vue,react推荐机制,需要babel转义成es5以兼容浏览器。 2.关于import...(from...) ①.import...from...的from命令后面可以跟很多路径格式,若只给出vue,axios这样的包名,则会自动到node_modules中加载;若给出相对路径及文件前缀,则到指定位置寻找。 ②.可以加载各种各样的文件:.js、.vue、.less等等。 ③.可以省略掉from直接引入。 3.关于export ①.导出的可以是对象,表达式,函数,类 ②.导出是为了让别人导入 4.言外话:使用es6的话,有一个特别好的规范去遵守,airbnb的es6规范(https://github.com/airbnb/javascript)
CommonJS:nodejs中使用较多,关键词是require,没写过node包,只引用过别人的模块,所以内部实现原理不是很清楚。
3.MVVM原理
MVVM是一种软件架构模式,MVVM有助于前后端分离。 View:视图层,粗略理解为DOM。 Model:与数据库对应的model,一般为json格式,作为req的body通过http(s)与数据库实现通信。 ViewModel:View与Model通过ViewModel实现双向绑定。
核心是提供对View和ViewModel的双向数据绑定,这样使得ViewModel的改变View立即变化,MVVM在前端的实现有:angular,vue,react。
vue中的常用数据双向绑定。
view:{{message}}
viewModel v-model="message"
model:message
<div id="app-6">
<p>{{ message }}</p>
<input v-model="message">
</div>
var app6 = new Vue({
el: '#app-6',
data: {
message: 'Hello Vue!'
}
})
单文件组件中的话,就多了一个用html5的template标签将view和viewModel包裹起来,model部分停留在script标签部分。
<template>
view
viewModel
</tamplate>
<script>
model
</script>
<styles>
为了让view好看点
</styles>
react的话,我在使用的过程中,没有听说过双向绑定的东西,对redux reducers推荐写为纯函数印象深刻,纯函数的话,感觉应该有点单项数据流的意思。
既然说到框架了,说一个最让我感觉有趣的点,那就是组件间的通信,对于简单组件,只涉及父子级别的通信的,vue使用on emit的方式,react使用props。对于复杂级别通信,爷爷父亲儿子孙子等等时,vue推荐使用vuex,react推荐使用redux,统一的全局状态树用来做状态管理非常好,可以使得逻辑非常清晰。vue项目文件结构研究不深,react的项目文件结构的话,presentational和containers的设计方法感觉非常有道理,一个负责视图一个负责数据,非常清爽。
4.最熟悉的框架路由机制 vue路由依赖:vue-router 通过组合组件来组成单页应用程序,只需要将组件映射到路由即可。 前端路由的核心,就在于 —— 改变视图的同时不会向后端发出请求。 需要注意2种模式的区别:hash模式和history模式,hash模式会在后面加一个很丑的#,可以开启history去掉。 hash模式原理:它的特点在于:hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。hash可以理解为锚点,例如./index.html/#/foo,hash值为#/foo,这样不会跳转页面。就相当于统一页面的不同锚点,页面间跳转与 ./index.html/#foo到./index.html/#bar类似。
./store/index.js
import Router from 'vue-router'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/common',
name: 'common',
component: Common
}
]
路由层面还会包括嵌套路由,动态路由以及重定向,相当于自己模仿浏览器请求然后服务器响应模式,其实不涉及向后端请求,仅在浏览器就可以实现页面跳转,前段时间我做的用户权限控制就用到了vue-router,相比MVC结构下的后端路由,清晰了不少,这样后端只要负责路由编写api就好。
5.状态管理 下面是我在用vuex做项目时的一些思考,简单修改了一下,也添加了一些关于redux的思考。
vuex state,前端data view,前端DOM actions,用户操作,引起data变化从而导致DOM变化。
多个组件(视图)共享状态:通俗来讲,就是多个组件间会通信时,导致从后端拿来的数据发生变化,当组件较多时,如果兄弟组件间的通信都依赖父组件进行通信,会导致组件间的耦合非常高,从而导致项目逻辑混乱,难以维护。
多个组件(视图)依赖于同一状态。 来自不同视图的行为需要变更同一状态。
全局单例模式管理,把组件的共享状态抽取出来 不管在组件树的哪个位置,任何组件都能获取状态或者触发行为!
实践出真知: 1.state存放在index.js中,创建的Store实例getter,mutations,actions等,可以分离出来 2.getters存放在getter.js中,数据流为state→getter→组件,getter相当于一个数据获取过滤器,从仓库拿特定数据到组件,相当于对computed的集中处理。 3.mutations存放在mutations.js中,数据流为组件→mutations→state,mutations相当于一个数据提交发射器,从组件提交数据到仓库 4.actions存放在actions.js中,数据流为组件→actions→mutations→state,异步操作的主要场所。 5.modules是开发大型应用时需要用到的,每个module都有单独的states,getters,actions以及mutation,有一股nodejs模块的味道。
vuex三原则: 1.唯一数据源 2.保持状态只读 3.数据改变只能通过纯函数完成 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
!!!mutation和action的区别!!!
mutation只变更本地的状态,也就是说,直接只去修改store中的数据。 action包含异步操作,直接调用api,通过api的数据,再提交mutation。
可以说,action只比mutation多了一个异步调用api的操作,因为调用api后,一般有2种返回结果,succes或者error,或者是promise的多种状态,根据不同的。
最近在学习redux,组件dispatch一个action到store,相当于发送一个http请求,然后store做出响应,返回一个response给组件。和vuex大致类似,唯一有区别的是,vuex还需要引入react-redux,引入Provider和connect连接组件和store。
6.统计字符串中单词出现次数 " hi how are you i am fine thank you youtube am am ",统计"you"出现的次数。
function wordCount(str,word){
var str = str || "";
var word = word || "";
var strArr = str.split(" ");
var count = 0;
for(var i=0;i<strArr.length;i++){
if(word===strArr[i]){
count++
}
}
return count;
}
wordCount("hi how are you i am fine thank you youtube am am","you");
如果字符串没有空格怎么办?
function wordCount(str,word){
var str = str || "";
var word = word || "";
var count = 0;
var index = str.indexOf(word);
while(index!==-1){
count++;
str = str.substr(index+word.length);
index = str.indexOf(word)
}
return count;
}
wordCount("hihowareyouiamfinethankyouyoutubeamam","you");
如果不用js内置字符串函数,自己用每个字符对比呢?
function wordCount(str,word){
var num = 0;
var str = str+" " || "";
var word = word || "";
var strArr = str.split("");
var wordArr = word.split("");
var count = 0;
function compare(arr1,a,arr2,b){
if(b+a<arr2.length){
if(arr1[a]===arr2[b+a]){
num++;
return compare(arr1,a+1,arr2,b+1)
}
if(num===arr1.length){
count++
num = 0;
}
}
}
for(var i=0;i<strArr.length;i++){
for(var j=0;j<wordArr.length;j++){
if(wordArr[wordArr.length-1]===strArr[i+wordArr.length-1]){
compare(wordArr,0,strArr,i+0)
}
}
}
return count;
}
wordCount("hihowareyouiamfinethankyouyoutubeamam","am");
可以更加高效一些吗?
function wordCount (str,word) {
var str = str+" " || "";
var word = word || "";
var strArr = str.split("");
var wordArr = word.split("");
var wordArrLen = wordArr.length;
var count = 0;
var num = 0;
function compare (arr1,a,arr2,b) {
if(b+a<arr2.length){
if(arr1[a]===arr2[b+a]){
num++;
return compare(arr1,a+1,arr2,b+1)
}
if(num===arr1.length){
count++;
num = 0;
}
}
}
var j = 0;
while(j<wordArrLen){
var i = 0;
while(i<strArr.length){
if(wordArr[wordArrLen -1]===strArr[i+wordArrLen -1]){
compare(wordArr,0,strArr,i+0);
}
i++;
}
j++;
}
return count;
}
wordCount("hihowareyouiamfinethankyouyoutubeamam","a");
//1.调整最高层级遍历数组,从37的2次方降到3的2次方,从1369降到9
//2.合并控制变量和控制条件,使用while替代for,去除JS引擎查询i,j是否存在的消耗,会稍微降低代码可读性
//3.对重复引用的wordArr.length,赋值给局部变量wordArrLen,在这里,Array.prototype.length的查询次数从3次降低到1次
统计字符串中单词出现次数 用 ' hi how are you i am fine thank you youtube am am '.match(/you/g)
岂不是更直接点
@zimplexing 这个方式不错,那如何用正则区分you和youtube呢?
看到这个题目也写了一下,我把题目理解成youtube里的you也要被搜索到,作者提到的减少计算次数那一块学习到了。
function count(str) {
let strArr = str.split(' ');
return strArr.filter(item=>item.includes('you')).length;
}
var countStrWithoutSpace=(function(){
var countx = 0
return function re(str) {
let idx = str.indexOf('you')
if (idx !== -1) {
countx++
str = str.slice(idx + 3)
return re(str)
} else {
return countx
}
}
})()
@FrankKai 加一个单词边界判断
' hi how are you i am fine thank you youtube am am '.match(/\b(?=you)\w{3}\b/g)
这样就区分了you
和youtube
' hi how are you i am fine thank you youtube am am '.match(/\syou\s/g);
这样就能匹配单词了。
' hihowareyouiamfinethankyouyoutubeamam '.match(/you/g);
这样就不用\s
来匹配前后空格。
' hi how are you i am fine thank you youtube am am '.split('you').length-1
@ChenMaoForever ' hi how are you i am fine thank youtube you youtube am am '.split('you').length-1 返回you的数目是4 😅
2020年12月28日更新:新题解 " hi how are you i am fine thank you youtube am am ",统计"you"出现的次数。
function countWord(str, target){
const words = str.split(" ");
let count = 0;
for(const word of words){
if(target === word){
count++;
}
}
return count;
}
学习到了,感谢
RT