MVC是一种设计模式,它将应用划分为3个部分:数据(模型)、展示层(视图)和用户交互层。结合一下下图,更能理解三者之间的关系。
image
换句话说,一个事件的发生是这样的过程
模型:用来存放应用的所有数据对象。模型不必知晓视图和控制器的细节,模型只需包含数据及直接和这些数据相关的逻辑。任何事件处理代码、视图模版,以及那些和模型无关的逻辑都应当隔离在模型之外。
视图:视图层是呈现给用户的,用户与之产生交互。在javaScript应用中,视图大都是由html、css和JavaScript模版组成的。除了模版中简单的条件语句之外,视图不应当包含任何其他逻辑。事实上和模型类似,视图也应该从应用的其他部分中解耦出来
控制器:控制器是模型和视图的纽带。控制器从视图获得事件和输入,对它们进行处理,并相应地更新视图。当页面加载时,控制器会给视图添加事件监听,比如监听表单提交和按钮单击。然后当用户和应用产生交互时,控制器中的事件触发器就开始工作。
例如JavaScript框架早期框架backbone就是采用的MVC模式。
上面的例子似乎太过空洞,下面讲一个生活中的例子进行讲解:
1、用户提交一个新的聊天信息
2、控制器的事件处理器被触发
3、控制器创建了一个新的聊天模型
4、然后控制器更新视图
5、用户在聊天窗口看到新的聊天信息
讲了一个生活的例子,我们用代码的方式更加深入了解MVC。
MVC中M表示model,与数据操作和行为相关的逻辑都应当放入模型中。例如我们创建一个Model对象,所有数据的操作都应该都放在这个命名空间中。下面是一些简化的代码,首先创建新模型和实例
var Model = {
create: function() {
this.records = {}
var object = Object.create(this)
object.prototype = Object.create(this.prototype)
return object
}
}
create用于创建一个以Model为原型的对象,然后就是一些包括数据操作的一些函数包括查找,存储
var Model = {
/*---代码片段--*/
find: function () {
return this.records[this.id]
},
save: function () {
this.records[this.id] = this
}
}
下面我们就可以使用这个Model了:
user = Model.create()
user.id = 1
user.save()
asset = Model.create()
asset.id = 2
asset.save()
Model.find(1)
=> {id:1}
可以看到我们就已经查找到了这个对象。模型也就是数据的部分我们也就完成了。
下面来讲讲mvc中的控制器。当加载页面的时候,控制器将事件处理程序绑定在视图中,并适时地处理回调,以及和模型必要的对接。下面是控制器的简单例子:
var ToggleView = {
init: function (view) {
this.view = $(view)
this.view.mouseover(this.toggleClass, true)
this.view.mouseout(this.toggleClass, false)
},
this.toggleClass: function () {
this.view.toggleClass('over', e.data)
}
}
这样我们就实现了对一个视图的简单控制,鼠标移入元素添加over class,移除就移除over class。然后在添加一些简单的样式例如
ex:
.over {color: red}
p{color: black}
这样控制器就和视图建立起了连接。在MVC中有一个特性就是一个控制器控制一个视图,随着项目体积的增大,就需要一个状态机用于管理这些控制器。先来创建一个状态机
var StateMachine = function() {}
SateMachine.add = function (controller) {
this.bind('change', function (e, current) {
if (controller == current) {
controller.activate()
} else {
controller.deactivate()
}
})
controller.active = function () {
this.trigger('change', controller)
}
}
// 创建两个控制器
var con1 = {
activate: funtion() {
$('#con1').addClass('active')
},
deactivate: function () {
$('#con1').removeClass('active')
}
}
var con2 = {
activate: funtion() {
$('#con2').addClass('active')
},
deactivate: function () {
$('#con2').removeClass('active')
}
}
// 创建状态机,添加状态
var sm = new StateMachine
sm.add(con1)
sm.add(con2)
// 激活第一个状态
con1.active()
这样就实现了简单的控制器管理,最后我们在添加一些css样式。
#con1, #con2 { display: none }
#con2.active, #con2.active { display: block }
当con1激活的时候样式就发生了变化,也就是视图发生了变化。
控制器也就讲到了这里,下面来看看MVC中的View部分,也就是视图
视图是应用的接口,它为用户提供视觉呈现并与用户产生交互。在javaScript种,视图是无逻辑的HTML片段,又应用的控制器来管理,视图处理事件回调以及内嵌数据。简单来说就是在javaScript中写HTML代码,然后将HTML片段插入到HTML页面中,这里讲两种方法:
使用document.createElement创建DOM元素,设置他们的内容然后追加到页面中,例如
var views = documents.getElementById(‘views’)
views.innerHTML = ‘’ // 元素清空
var wapper = document.createElement(‘p’)
wrapper.innerText = ‘add to views’
views.appendChild(wrapper)
这样就完成了用createElement创建元素,然后添加到HTML页面中。
如果以前有过后端开发经验,那么对模版应该比较熟悉。例如在nodejs中常用的就是ejs,下面是ejs的一个小例子,可以看到的是ejs将javascript直接渲染为HTML
str = '<h1><%= title %></h1>'
ejs.render(str, {
title: 'ejs'
});
那么这个渲染后的结果就是
var addChange = function (ob) {
ob.change = function (callback) {
if (callback) {
if (!this._change) this._change = {}
this._change.push(callback)
} else {
if (!this._change) return
for (var i = this._change.length - 1; i >= 0; i--) {
this._change[i].apply(this)
}
}
}
}
我们来看看一个实际的例子
var addChange = function (ob) {
ob.change = function (callback) {
if (callback) {
if (!this._change) this._change = {}
this._change.push(callback)
} else {
if (!this._change) return
for (var i = this._change.length - 1; i >= 0; i--) {
this._change[i].apply(this)
}
}
}
}
var object = {}
object.name = 'Foo'
addChange(object)
object.change(function () {
console.log('Changed!', this)
// 更新视图的代码
})
obejct.change()
object.name = 'Bar'
object.change()
这样就实现了执行和触发change事件了。
我相信大家对MVC有了比较深刻的理解,下面来学习MVVM模式。
如今主流的web框架基本都采用的是MVVM模式,为什么放弃了MVC模式,转而投向了MVVM模式呢。在之前的MVC中我们提到一个控制器对应一个视图,控制器用状态机进行管理,这里就存在一个问题,如果项目足够大的时候,状态机的代码量就变得非常臃肿,难以维护。还有一个就是性能问题,在MVC中我们大量的操作了DOM,而大量操作DOM会让页面渲染性能降低,加载速度变慢,影响用户体验。最后就是当Model频繁变化的时候,开发者就主动更新View,那么数据的维护就变得困难。世界是懒人创造的,为了减小工作量,节约时间,一个更适合前端开发的架构模式就显得非常重要。这时候MVVM模式在前端中的应用就应运而生。
MVVM让用户界面和逻辑分离更加清晰。下面是MVVM的示意图,可以看到它由Model、ViewModel、View这三个部分组成。
image
下面分别来讲讲他们的作用
View是作为视图模板,用于定义结构、布局。它自己不处理数据,只是将ViewModel中的数据展现出来。此外为了和ViewModel产生关联,那么还需要做的就是数据绑定的声明,指令的声明,事件绑定的声明。这在当今流行的MVVM开发框架中体现的淋淋尽致。在示例图中,我们可以看到ViewModel和View之间是双向绑定,意思就是说ViewModel的变化能够反映到View中,View的变化也能够改变ViewModel的数据值。那如何实现双向绑定呢,例如有这个input元素:
<input type='text' yg-model='message'>
随着用户在Input中输入值的变化,在ViewModel中的message也会发生改变,这样就实现了View到ViewModel的单向数据绑定。下面是一些思路:
那么ViewModel到View的绑定可以是下面例子:
<p yg-text='message'></p>
渲染后p中显示的值就是ViewModel中的message变量值。下面是一些思路:
ViewModel起着连接View和Model的作用,同时用于处理View中的逻辑。在MVC框架中,视图模型通过调用模型中的方法与模型进行交互,然而在MVVM中View和Model并没有直接的关系,在MVVM中,ViewModel从Model获取数据,然后应用到View中。相对MVC的众多的控制器,很明显这种模式更能够轻松管理数据,不至于这么混乱。还有的就是处理View中的事件,例如用户在点击某个按钮的时候,这个行动就会触发ViewModel的行为,进行相应的操作。行为就可能包括更改Model,重新渲染View。
Model 层,对应数据层的域模型,它主要做域模型的同步。通过 Ajax/fetch 等 API 完成客户端和服务端业务 Model 的同步。在层间关系里,它主要用于抽象出 ViewModel 中视图的 Model。
实现效果:
<div id="mvvm">
<input type="text" v-model="message">
<p>{{message}}</p>
<button v-click='changeMessage'></button>
</div>
<script type="">
const vm = new MVVM({
el: '#mvvm',
methods: {
changeMessage: function () {
this.message = 'message has change'
}
},
data: {
message: 'this is old message'
}
})
</script>
这里为了简单,借鉴了Vue的一些方法
MVVM为我们省去了手动更新视图的步骤,一旦值发生变化,视图就重新渲染,那么就需要对数据的改变就行检测。例如有这么一个例子:
hero = {
name: 'A'
}
这时候但我们访问hero.name 的时候,就会打印出一些信息:
hero.name
// I'm A
当我们对hero.name 进行更改的时候,也会打印出一些信息:
hero.name = 'B'
// the name has change
这样我们是不是就实现了数据的观测了呢。
在Angular中实现数据的观测使用的是脏检查,就是在用户进行可能改变ViewModel的操作的时候,对比以前老的ViewModel然后做出改变。
而在Vue中,采取的是数据劫持,就是当数据获取或者设置的时候,会触发Object.defineProperty()。
这里我们采取的是Vue数据观测的方法,简单一些。下面是具体的代码
function observer (obj) {
let keys = Object.keys(obj)
if (typeof obj === 'object' && !Array.isArray(obj)) {
keys.forEach(key => {
defineReactive(obj, key, obj[key])
})
}
}
function defineReactive (obj, key, val) {
observer(val)
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function () {
console.log('I am A')
return val
},
set: function (newval) {
console.log('the name has change')
observer(val)
val = newval
}
})
}
把hero带入observe方法中,结果正如先前预料的一样的结果。这样数据的检测也就实现了,然后在通知订阅者。如何通知订阅者呢,我们需要实现一个消息订阅器,维护一个数组用来收集订阅者,数据变动触发notify(),然后订阅者触发update()方法,改善后的代码长这样:
function defineReactive (obj) {
dep = new Dep()
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function () {
console.log('I am A')
Dep.target || dep.depend()
return val
},
set: function (newval) {
console.log('the name has change')
dep.notify()
observer(val)
val = newval
}
})
}
var Dep = function Dep () {
this.subs = []
}
Dep.prototype.notify = function(){
var subs = this.subs.slice()
for (var i = 0, l = subs.length; i < l; i++) {
subs[i].update()
}
}
Dep.prototype.addSub = function(sub){
this.subs.push(sub)
}
Dep.prototype.depend = function(){
if (Dep.target) {
Dep.target.addDep(this)
}
}
这跟Vue源码差不多,就完成了往订阅器里边添加订阅者,和通知订阅者。这里以前我看Vue源码的时候,困扰了很久的问题,就是在get方法中Dep是哪儿来的。这里说一下他是一个全局变量,添加target变量是用于向订阅器中添加订阅者。这里的订阅者是Wacther,Watcher就可以连接视图更新视图。下面是Watcher的一部分代码
Watcher.prototype.get = function(key){
Dep.target = this
this.value = obj[key] // 触发get从而向订阅器中添加订阅者
Dep.target = null // 重置
};
在讲MVVM概念的时候,在View -> ViewModel的过程中有一个步骤就是在DOM tree中寻找哪个具有yg-xx的元素。这一节就是讲解析模板,让View和ViewModel连接起来。遍历DOM tree是非常消耗性能的,所以会先把节点el转换为文档碎片fragment进行解析编译操作。操作完成后,在将fragment添加到原来的真实DOM节点中。下面是它的代码
function Compile (el) {
this.el = document.querySelector(el)
this.fragment = this.init()
this.compileElement()
}
Compile.prototype.init = function(){
var fragment = document.createDocumentFragment(), chid
while (child.el.firstChild) {
fragment.appendChild(child)
}
return fragment
};
Compile.prototype.compileElement = function(){
fragment = this.fragment
me = this
var childNodes = el.childNodes
[].slice.call(childNodes).forEach(function (node) {
var text = node.textContent
var reg = /\{\{(.*)\}\}/ // 获取{{}}中的值
if (reg.test(text)) {
me.compileText(node, RegExp.$1)
}
if (node.childNodes && node.childNodes.length) {
me.compileElement(node)
}
})
}
Compile.prototype.compileText = function (node, vm, exp) {
updateFn && updateFn(node, vm[exp])
new Watcher(vm, exp, function (value, oldValue) {
// 一旦属性值有变化,就会收到通知执行此更新函数,更新视图
updateFn() && updateFn(node, val)
})
}
// 更新视图
function updateFn (node, value) {
node.textContent = value
}
这样编译fragment就成功了,并且ViewModel中值的改变就能够引起View层的改变。接下来是Watcher的实现,get方法已经讲了,我们来看看其他的方法。
Watcher是连接Observer和Compile之间的桥梁。可以看到在Observer中,往订阅器中添加了自己。dep.notice()发生的时候,调用了sub.update(),所以需要一个update()方法,值发生变化后,就能够触发Compile中的回调更新视图。下面是Watcher的具体实现
var Watcher = function Watcher (vm, exp, cb) {
this.vm = vm
this.cb = cb
this.exp = exp
// 触发getter,向订阅器中添加自己
this.value = this.get()
}
Watcher.prototype = {
update: function () {
this.run()
},
addDep: function (dep) {
dep.addSub(this)
},
run: function () {
var value = this.get()
var oldVal = this.value
if (value !== oldValue) {
this.value = value
this.cb.call(this.vm, value, oldValue) // 执行Compile中的回调
}
},
get: function () {
Dep.target = this
value = this.vm[exp] // 触发getter
Dep.target = null
return value
}
}
在上面的代码中Watcher就起到了连接Observer和Compile的作用,值发生改变的时候通知Watcher,然后Watcher调用update方法,因为在Compile中定义的Watcher,所以值发生改变的时候,就会调用Watcher()中的回调,从而更新视图。最重要的部分也就完成了。在加一个MVVM的构造器就ok了。推荐一篇文章自己实现MVVM,这里边讲的更加详细。
ok,本篇文章就结束了,通过对比希望读者能够对前端当前框架能够更清晰的认识。谢谢大家
表格如果字段多,有横向滚动条是不是不方便?可拖拽的滚动是不是就方便了?
使用create-vue创建vue3项目,vite,vue3
相对VUE2 ,VUE3做了哪些优化和改进呢?
Beyond Compare4试用30天到期了,怎么操作?买吗?去吧
正则如果匹配键盘上的所有特殊字符?中文的特殊字符又如何匹配?
如果下载正版的,不带流氓软件的系统IOS文件镜像
vue项目,不使用window.location.reload(),如何刷新当前页面?
使用moment.js对时间进行加减操作,使得fomrat输出对应的格式,取0点的时间缀和24点的时间缀
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
ant.design 4.x获取form表单的方式
ant.design v5 and 中如何在class中使用umijs的useModel调用initialState
vue2.0 v-html指令有潜在的xss风险,如何解决?
vue项目通过axios怎么下载二进制文件或图片?
ant.design UI框架 同时使用v-model或value属性时, placeholder不显示
Problems loading reference 'http://json.schemastore.org/package': Unable to load schema from 'http://json.schemastore.org/package': Bad request. The request cannot be fulfilled due to bad syntax. Invalid header received from client. .
如何在VUE项目中添加stylelint,检查css,scss,less的语法问题,保证团队代码的规范统一
react之ref提示:Using string literals in ref attributes is deprecated,不能使用字符串,怎么处理?
react不能在 render里设置state,也不能在componentWillReceiveProps里设置state,会导致性能问题。如果要通过属性改变state,怎么做呢?可以利用getDerivedStateFromProps生命周期函数
JS生成树形菜单
利用nginx服务器推送关键静态资源,加快网站打开速度
VUE全局函数
定义了服务端渲染的属性名称常量SSR_ATTR,定义了一些资产类型常量ASSET_TYPES,定义了生命周期相关钩子函数的函数名称
if(a==1 && a==2 && a==3){ console.log('hello"); }
MVC是一种设计模式,它将应用划分为3个部分:数据(模型)、展示层(视图)和用户交互层。结合一下下图,更能理解三者之间的关系。
所谓的垃圾回收其实是内存释放的过程,我们用JS定义变量、对象时,系统会为它们分配内存,如果这一块的内存得不到释放,那么内存会耗尽(这就是所谓的内存泄漏)
Fetch 是 web异步通信的未来. 从chrome42, Firefox39, Opera29, EdgeHTML14(并非Edge版本)起, fetch就已经被支持了. 其中chrome42~45版本, fetch对中文支持有问题, 建议从chrome46起使用fetch.
`super`关键字用于访问和调用一个对象的父对象上的函数。 `super.prop`和`super[expr]`表达式在类和对象字面量任何方法定义中都是有效的。 在构造函数中使用时,`super`关键字将单独出现,并且必须在使用`this`关键字之前使用。`super`关键字也可以用来调用父对象上的函数。
对象是 JavaScript 语言最主要的数据类型,三种原始类型的值——数值、字符串、布尔值——在一定条件下,也会自动转为对象,也就是原始类型的“包装对象”
在 JavaScript 中,判断一个变量的类型尝尝会用 typeof 运算符,在使用 typeof 运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,它都返回 &amp;amp;quot;object&amp;amp;quot;。ECMAScript 引入了另一个 Java 运算符 instanceof 来解决这个问题。instanceof 运算符与 typeof 运算符相似,用于识别正在处理的对象的类型。与 typeof 方法不同的是,instanceof 方法要求开发者明确地确认对象为某特定类型。
JS数组去重的各种方法~
使用iviewui-admin框架构建管理系统时,遇到的各类问题
使用es6的exports和import 进行模块化开发
vue项目中动态图片路径拼接
vue下filter方法的调用
对于 HTTP头Cache-Control,我们经常使用,也非常&amp;quot;熟悉&amp;quot;,然后经常会有问题,为什么我使用了&amp;quot;no-cache&amp;quot;,然后为什么还有缓存? 看这个文章你就知道为什么了。
在之前,我们要判断一个元素是否出现在视窗内,需要使用`scroll`或`setInterval`来不断计算元素的位置,这样非常损耗性能,Chrome在2016年的时候推出了IntersectionObserver APi,现在看看它是做什么的
21个vue顶级UI框架: Vuetify,Quasar,Vue Material,Keen-UI,Buefy,Bootstrap Vue,Muse-UI,AT-UI,Vux,iView,Uiv,Vuikit,Onsen UI+Vue,Semantic UI+Vue,Fish-UI,Mint UI,Framework7 Vue,Cube UI,Vueblu,Ant Design Vue
轻量高效的开源JavaScript插件和库
格式化input输入~
&amp;amp;quot;.vue&amp;amp;quot;文件是如何解析成js对象的~
立个flag,看过年这段时间能不能把vue的源码读完?多年前看过jQuery的部分源码,如果想要更深入的了解vue,还是得从源码开始
vue源码阅读,慢慢学习
vue的生命周期函数
Next.js 是一个轻量级的 React 服务端渲染应用框架。
使用原生window.atob和btoa进行base64编码解码
NodeJieba是&amp;amp;amp;quot;结巴&amp;amp;amp;quot;中文分词的 Node.js 版本实现, 由CppJieba提供底层分词算法实现, 是兼具高性能和易用性两者的 Node.js 中文分词组件。
通过箭头函数或bind方式,对绑定事件传参
vue组件的数据data为什么一定要是函数 ?
回顾一下NaN,isNaN,Number.isNaN
React Hot Loader是一个插件,允许React组件在不丢失状态的情况下进行实时重新加载。它适用于Webpack和其他支持热模块替换(HMR)和Babel插件的捆绑器
如果你查看目前任何主流的项目中的`devDependencies`,会发现前些年的不计其数的插件诞生。我们归纳一下有:javascript转译、代码压缩、css预处理器、elint、pretiier,等。有很多js模块我们不会在生产环境用到,但是它们在我们的开发过程中充当着重要的角色。所有的上述工具,不管怎样,都建立在了AST这个巨人的肩膀上
在第一部分中我们了解了许多基础知识,结束了语法的学习,我们可以进入下一个更有趣的部分:使用静态类型的优势和劣势
作为一个JavaScript开发者,你可以编写一整天编写也不会遇到任何静态类型检查得问题。那么为什么要自找麻烦得去学习它呢? 然而学习静态类型并不仅仅是一个思维拓展的训练。如果你愿意花点时间来学习一些静态类型的优势、劣势以及使用的案例,那将会极大的帮助你进行编码。 怎么样,有意思吧?要是你感兴趣的话,那接下来四个部分将会向你详细解释
Warning: `getFieldDecorator` will override `value`, so please don't set `value` directly and use `setFieldsValue` to set it.
Mint-ui this.$messagebox点取消时,报错:Uncaught (in promise) cancel
vue-validate使用
这就是个vue的坑。。。
vue如何监听enter事件?
vue使用axios进行form表单提交
这一节,我们会讨论词法环境的细节,它是在一些编程语言中用于管理静态作用域的一种机制。为了确保能充分理解这一主题,我们会简要讨论下其对立面:动态作用域(并没有直接用于 ECMAScript)。我们会看到环境是如何管理代码中的词法嵌套结构,以及为闭包提供全面支持。
vue中如何改变title标题
如果在vue2.0中使用NProgress进度条
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。也是vue2.0官方推荐的,同时不再对vue-resource(vue1.0使用)进行更新和维护
React 的核心思想是:封装组件。 各个组件维护自己的状态和 UI,当状态变更,自动重新渲染整个组件。 基于这种方式的一个直观感受就是我们不再需要不厌其烦地来回查找某个 DOM 元素,然后操作 DOM 去更改 UI
这一章专门讨论了ECMA-262-5 规范的新概念之一 — 属性特性及其处理机制 — 属性描述符。 当我们说“一个对象有一些属性”的时候,通常指的是属性名和属性值之间的关联关系。但是,正如在ES3系列文章中分析的那样,一个属性不仅仅是一个字符串名,它还包括一系列特性—比如我们在ES3系列文章中已经讨论过的{ReadOnly},{DontEnum}等。因此从这个观点来看,一个属性本身就是一个对象
分析Vue.js源码
npm run dev模式下,webpack4+vue2项目下,类似'/user/login'二级路由,刷新时静态资源路径不对,静态资源返回404
[Vue warn]: Error in render: "TypeError: Cannot read property 'matched' of undefined"
did you register the component correctly? For recursive components, make sure to provide the "name" option
vue.js如何查看注册了哪些组件,获取组件名称
本教程全面介绍 JavaScript 核心语法,从最简单的讲起,循序渐进、由浅入深,力求清晰易懂。所有章节都带有大量的代码实例,便于理解和模仿,可以用到实际项目中,即学即用。
《ECMAScript 6 入门》是一本开源的 JavaScript 语言教程,全面介绍 ECMAScript 6 新引入的语法特性。
vue底层的Virtual DOM就是基于snabbdom修改的
这一章的第二部分是关于EMCAScript中的面向对象编程。在第一部分中我们讨论了OOP的基本理论并勾画出和ECMAScript的相似之处。在阅读第二部分之前,如果有必要,我还是建议首先阅读这一章的第一部分.基本理论,因为后面将会用到其中的一些术语。
这一章我们讨论ECMAScript中面向对象编程(object-oriented programming)的几个主要方面。由于这一主题已经在许多文章中谈论过,本章并不打算“老调重弹”,而是试图更多地着眼于这些过程内在的理论方面。尤其是,我们将研究对象创建的算法,看看对象间的关系(包括最基本的关系——继承)是如何实现的,并且给出一些讨论中将用到的准确定义(我希望这样能够打消一些术语和思路上的疑惑以及一些关于Javascript文章中OOP部分的常见的混淆)。
在这一章中我们来谈谈Javascript中被讨论最多的话题之一——关于闭包(closures)。事实上这个主题并不是新鲜的。然而我们在这里将试着更多从理论的角度去分析和理解它,然后我们还会看一下ECMAScript内关于闭包的内容。
在这章里我们讨论ECMAScript中的一个基本对象——函数。我们将会看到不同类型的函数如何影响一个上下文中的变量对象,以及这些函数的作用域链中都包含什么。我们将会回答像下面这样经常被问到的问题:“下面这两种创建函数的方式有什么区别吗(如果有的话,区别是什么呢)?”
正如我们从第二章.变量对象中了解到的,执行上下文的数据(变量,函数声明,函数形参)以变量对象的属性的方式储存。
许多程序员习惯于认为在编程语言中,this关键字是与面向对象编程紧密相关的,而且引用的是由构造式最新创建的对象。在ECMAScript中,这个概念也被实现了,然而我们将看到,在这里它不仅仅指向已创建的对象。
在程序中我们总是声明变量和函数然后用它们来搭建我们的系统。但是解释器(interpreter)是在哪里和以什么方式来找到我们的数据(函数,变量)的呢?
第1章:在这一章里,我们将会讨论ECMAScript中的执行上下文(execution context)以及与它们相关的可执行代码(executable code)的类型。
检测这种缩放有很种方法,QQ空间都通过flash来检测浏览器是否处于缩放。这里提供javascript的方法来检测浏览器的缩放。
当你的项目中的时间需要考虑时区,夏令时时,下面判断夏令时的方法就很有用了!
在以前的编码过程中,对for...in遍历对象的循环的,一直以为是没有顺序的。直到遇到有对象有的key值为纯数字时,发现现代浏览器对for...in循环是有顺序之分的。
有时候我们需要把网页的右键菜单禁用,然后启用自己模似的右键菜单。或者我们为了避免用户习惯性的使用F5刷新或使用Ctrl+r键刷新导致表单数据的丢失,我们还需要把F5键和ctrl+r键都屏蔽掉。甚至根据需要还可能会屏蔽退格键(Backspace)和退出键(Esc)。
preventDefault它是事件对象(Event)的一个方法,作用是取消一个目标元素的默认行为。既然是说默认行为,当然是元素必须有默认行为才能被取消,如果元素本身就没有默认行为,调用当然就无效了。什么元素有默认行为呢?如链接<a>,提交按钮<input type="submit">等。当Event 对象的 cancelable为false时,表示没有默认行为,这时即使有默认行为,调用preventDefault也是不会起作用的
通过JS检测网络是否OK,最简单粗暴的方式就是加载网络资源,JS文件或者图片文件...
什么是类数组?相信我们对function方法的arguments很熟悉,arguments就像一个数组,但instanceof Array检测会返回false,可以称为“类数组”。
利用iframe实现跨域
项目使用了setMonth来设置时间,发现了一个问题,2月份设置下去,显示出来变成3月份了。
jQuery是现在最流行的js库,一般情况下我们都会放心的使用它,不用考虑其内存泄漏的问题。 最近的项目是基于MVC模式的管理系统,期间要采用ajax不断轮询服务器,以获得最新的数据,这时候使用jQuery的时候就要注意了,一不小心俺们最可爱的IE内存就up up up了~~
除了正常运行模式,ECMAscript 5添加了第二种运行模式:"严格模式"(strict mode)。顾名思义,这种模式使得Javascript在更严格的条件下运行。
IE提示expected 错误,如果语法没问题,不防检查下是不是文件编码问题,改为utf-8试试
javascript原始数据类型相互转换示例,如字符串、数字、布尔类型的相互转换
arguments是调用对象的一个属性,它与形参及局部变量是一样的,它实际上是调用了一个Arguments对象,Arguments对象与数组相似,但它又不是数组,因为它不具备数组的一些常用方法,如push,sort,shift等等。Arguments对象有两个属性:
利用javascript开发WEB功能时,代码量小还OK,如果代码非常庞大,这就不可避免的出现一些未知的错误。如果web已经上线,这时却出现了js脚本错误,这对WEB的用户体验是致使的,因为一但出现js脚本错误,网页将停止加载,从而不能正常显示出页面,而失去用户。
一般情况下,判断javasceript数据类型,使用typeof 或 instanceof 就够了,但偶觉得用起来还是别别扭扭的。这里介绍一个完美的方法,我们可以轻松的判断数组,对象(这里对象暂且指{}),函数(function),布尔(Boolean),null,undefined,number,时间对象(date),正则表达式(RegExp)。
目前完成的一个基于MVC模式的管理系统,综合考虑后,选择了doT.js,这篇文章主要也是介绍下它的优势及使用方法。
移动光标到文字末尾,如果使用<input><textarea>时,需要把光标定位在文字的后面