JavaScript学习笔记
Posted 君兮月影
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript学习笔记相关的知识,希望对你有一定的参考价值。
文章目录
第1章:什么是javascript
1. JavaScript实现
- 核心(ECMAScript):由ECMA-262定义并提供核心功能
- 文档对象模型(DOM):提供与网页内容交互的方法和接口
- 浏览器对象模型(BOM):提供与浏览器交互的方法和接口
2. ECMAScript
- ECMA-262定义的一种语言基准,在此基础上构建更稳健的脚本语言
- Web浏览器只是ECMAScript实现的一种宿主环境(host environment),Node.js是服务器端JavaScript平台,也是一种宿主环境。
- ECMA-262定义了:语法,类型,语句,关键字,保留字,操作符,全局对象
3. DOM
- 文档对象模型,Document Object Model,是API。
- DOM将页面抽象为一组分层节点,创建表示文档的树。
4. BOM
- 浏览器对象模型,也是API。
- 通常把任何特定于浏览器的扩展都归在BOM的范畴内。
- 没有标准,html5之后,BOM实现细节日趋一致。
第2章:HTML中的JavaScript
1.<Script>元素
- 将JavaScript插入HTML的主要方法是使用<script>元素
- 是HTML规范
- <script>元素有8个属性
- async:可选。立即开始下载脚本,但不阻止其他页面动作,异步。
- charset:可选。使用src属性指定的代码字符集,很少用,因为大多数浏览器不care它的值。
- crossorigin:可选。配置相关请求的CORS(跨资源共享)设置,默认不使用CORS。
- defer:可选。表示脚本可以延迟到文档完全被解析和显示之后再执行。
- integrity:可选。用于确保内容分发网络(CDN,Content Delivery Network)不会提供恶意内容。
- language:废弃。
- src:可选。表示包含要执行的代码的外部文件的URL,可以跟网页在同一台服务器上,也可以位于完全不同的域。
- type:可选。代替language,表示代码块中脚本语言的内容类型(也称MIME类型)。例:“text/javascript”
- 使用方式
- 网页中嵌入JavaScript代码
- 在网页中包含JavaScript文件
- 使用了src属性的<script>元素不应该再在<script>和</script>标签中再包含其他JavaScript代码。如果两者都提供的话,浏览器只会下载并执行脚本文件,忽略行内代码。
- 建议将JavaScript引用放在<body>元素中的页面内容后面,因为页面在浏览器解析到<body>的起始标签时开始渲染,放在前面会导致页面渲染的明显延迟。
- 推迟执行脚本:defer属性。该属性只对外部脚本文件有效。HTML5规范要求脚本应该按照出现顺序执行,所以第一个defer的脚本会在第二个defer的脚本之前执行。但实际上不一定,so最好只包含一个defer脚本。因为有的浏览器会忽略这个属性,所以还是把要推迟执行的脚本放在页面底部比较好。
- 异步执行脚本:async属性。也只适用于外部脚本。但是标记为async的脚本不能保证按照出现次序执行,因为它们之间没有依赖关系。
- 动态加在脚本:使用DOM API,通过向DOM中动态添加script元素加载指定的脚本。只要创建一个script元素并将其添加到DOM即可。这种方式以异步加载,相当于添加了async属性,但是不是所有的浏览器都支持这个属性,所以可以将其设置为同步加载。
let script =document.createElemnet('script')`` script.src='gibberish.js' script.async = false; // 设置为同步加载 document.head.apendChild(script)
这种方式获取的资源对浏览器的预加载器不可见,严重影响性能。要想让预加载器知道动态请求文件的存在,可以在文档头部显式声明它们:
<link rel="preload" href="gibberish.js">
- XHTML中的变化:XHTML中使用JavaScript必须指定type属性且值为text/javascript。XHTML模式会在页面的MIME类型被指定为"application/xhtml+xml"时触发。
2.行内代码于外部文件
- 推荐使用外部文件,理由如下
- 可维护性。用一个目录保存所有的js文件,更容易维护,开发者可以独立于使用它们的HTML页面来编辑代码。
- 缓存。浏览器会根据特定的设置缓存所有外部链接的js文件,所以如果两个页面都用到同一个文件,只需要下载一次,从而使页面加载更快。
- 适应未来。包含外部js文件的语法在HTML和XHTML中一样。
3.文档模式
- 使用doctype切换文档模式
- 混杂模式(quirks mode):省略文档开头的doctype声明
- 标准模式(standards mode)
- 准标准模式(almost standards mode)
4.<noscript>元素
- 用于给不支持js的浏览器提供替代内容。
- 如今的浏览器已经100%支持js
- 对于禁用js的浏览器来说,这个元素有用
第3章 语言基础
1.语法
- 区分大小写
- 标识符:
- 可以由一个或多个字符组成,第一个字符必须是一个字母,下划线(_)或美元符号($),剩下的其他字符可以是字母、下划线、美元符号或数字。
- 按照惯例使用驼峰大小写形式,不是强制性的。
- 关键字、保留字、true、false和null不能作为标识符。
- 注释:
- 单行注释:// 注释内容
- 多行注释:/* 注释内容 */
- 严格模式(strict mode):
- "use strict"启用严格模式,可以对整个脚本启用,也可以对指定函数启用,这是一个预处理指令。
- 所有现代浏览器都支持严格模式。
- 语句
- 以分号结尾,没有分号意味着由解析器确定语句在哪结尾,也有效,但不推荐。
- 多条语句可以合并到一个代码块中,代码块由 ‘’ 标识开始,''标识结束。
- if之类的控制语句只在执行多条语句时要求必须有代码块,但推荐加代码块,减少出错。
2.关键字与保留字
- 关键字
- 保留字
3.变量
- var关键字
- 可以保存任何类型的值,没有初始化的情况下保存一个特殊值undefined
- 可以同时定义变量并设置它的值
- 可以改变保存的值,也可以改变值的类型
- var声明作用域:在函数内部定义的变量只在函数内部有效,在函数内定义变量时省略var操作符,可以创建一个全局变量,但不推荐这么做。
- 定义多个变量可以在一条语句中用逗号分隔
- var声明提升:var声明的变量会自动提升到函数作用域顶部
- 反复使用var声明同一个变量也没有问题
- let声明
- let声明的范围是块作用域,而var声明的范围是函数作用域,块作用域是函数作用域的子集
- let不允许同一个块作用域中出现冗余声明
- 暂时性死区:let与var的一个重要区别是,let声明的变量不会在作用域中被提升。let声明之前的执行瞬间被称为“暂时性死区”(temporal dead zone),在此阶段引用任何后面才声明的变量都会抛出ReferenceError。
- 全局声明:let在全局作用域中声明的变量不会成为window对象的属性(var声明的变量会)。
- 条件声明:不能使用let进行条件式声明(条件声明是一种反模式)
- for循环中的let声明:使用let声明for循环中的迭代变量,则变量的作用域仅限于for循环块内部,不会出现渗透到循环体外部的情况。
- const声明
- 声明变量时必须同时初始化变量。
- 尝试修改const声明的变量会导致运行时错误。不能声明迭代变量。
- 不允许重复声明。
- 声明的作用域也是块。
- const声明的限制只适用于它指向的变量的引用,可以修改这个对象内部的属性。
- 声明风格及最佳实践
- 不使用var
- const优先,let次之
4.数据类型
- 简单数据类型:Undefined、Null、Boolean、Number、String和Symbol。
- 复杂数据类型:Object
- typeof操作符:用来确定变量的数据类型,只是一个操作符,不是函数,不需要参数(当然也可以使用参数)
- Undefined类型:
- 只有一个值,就是特殊值undefined。
- 当var和let声明了变量但是没有初始化时,默认给变量赋值undefined。
- 不必显式地将变量值设置为undefined。
- 注意:无论是声明后未赋值还是未声明,typeof返回的都是"undefined",逻辑上是对的。建议在声明变量的同时初始化,这样当typeof返回"undefined"的时候就知道是未声明而不是声明了但未初始化。
- Null类型:
- 只有一个值,特殊值null。表示一个空对象指针。
- 当一个变量要保存对象而又没有对象可保存时,将变量显式的赋值为null。
- 注意:用比较操作符(==)比较null和undefined始终返回true。
- Boolean类型:
- 有两个字面值:true,false
- Boolean()转型函数:将其他类型的值转换为布尔值
- Number类型
- 八进制:第一位必须为0,严格模式下无效。应该使用前缀0o
- 十六进制:前缀0x。
- 浮点值:
- 数值中必须包含小数点,小数点后面必须至少有一个数字。小数点前不是必须有整数,但推荐加上。
- 科学计数法表示:一个数值(整数或浮点数)后跟一个大写或小写的字母e,再加上一个要乘的10的多少次幂。例:3.125e7,3e-17。
- 值的范围:
- 最小值:Number.MIN_VALUE,大概是5e-324。
- 最大值:Number.MAX_VALUE,大概是1.797 693 134 862 315 7e+308。
- 任何无法表示的负数:-Infinity(负无穷大),Number.NEGATIVE_INFINITY
- 任何无法表示的正数:Infinity(正无穷大),Number.POSITIVE_INFINITY
- 如果计算返回正 Infinity 或负 Infinity,则该值将不能再进一步用于任何计算。
- isFinite()函数:用于确定一个数是不是有限大。
- NaN
- 不是数值,not a number。用于表示本来要返回数值的操作失败了。
- 任何涉及NaN的操作始终返回NaN。
- NaN不等于包括NaN在内的任何值。
- isNaN()函数:接受一个参数,判断该参数是否“不是数值”。
- 数值转换:有三个函数可以将非数值转换为数值
- Number():可用于任何数据类型。
- parseInt():主要用于将字符串转换为数值。可以接收两个参数,第二个参数表示底数(进制数)。建议给第二个参数。
- parseFloat():主要用于将字符串转换为数值。
- String类型
- 0个或多个16位Unicode字符序列
- 可以用双引号(")、单引号(')或反引号(`)标示
- 字符串的长度通过length属性过去,例:text.length
- toString()方法:把一个值转换为字符串。对数值调用这个方法时,可以接受一个底数参数。null和undefined值没有这个方法。
- String():当不确定一个值是不是null或undefined时用。
- 用加号操作符给一个值加上一个空字符串""也可以将其转换为字符串。
- 字符串差值:通过在$中使用一个JavaScript表达式实现。嵌套的模板字符串无须转义,在插值表达式中可以调用函数和方法。模板也可以插入自己之前的值。
- 模板字面量标签函数(没看懂!,到底什么是标签函数啊?)第67页
- 原始字符串:String.raw标签函数,也可以通过标签函数的raw属性获得每个字符串的原始内容
- Symbol类型:(这里面蛮多不懂的地方,用到的时候再回来看)
- 符号类型,确保对象属性使用唯一标识符。
- 基本用法:
- 使用Symbol()函数初始化。let sym = Symbol();
- 调用Symbol()函数时,可以传入一个字符串参数作为对符号的描述,let othersym = Symbol(‘foo’);这个字符串参数可以用来调试代码,但是与符号定义或标识完全无关。
- 符号没有字面量语法
- Symbol()函数不能与new关键字一起作为构造函数使用
let mySymbol = new Symbol(); // TypeError: Symbol is not a constructor
- 使用全局符号注册表
- 使用Symbol.for()方法:
let fooGlobalSymbol = Symbol.for('foo');
- 在全局注册表中定义的符号跟使用Symbol()定义的符号并不等同。
- 全局注册表中的符号必须使用字符串来创建,因此作为参数传给Symbol.for()的任何值都会被转换为字符串。注册表中使用的键同时也会被用作符号描述。
let emptyGlobalSymbol = Symbol.for();
console.log(emptyGlobalSymbol); // Symbol(undefined)
- 使用Symbol.keyFor()来查询全局注册表,返回该全局符号对应的字符串键。
// 创建全局符号
let s = Symbol.for('foo');
console.log(Symbol.keyFor(s)); // foo
- 使用Symbol.for()方法:
- 使用符号作为属性(从这里开始往下的符号部分的内容没看懂,用到的时候再回来看)
- 常用内置符号
- Object类型:
- 对象实际就是一组数据和功能的集合。通过new操作符后跟对象类型的名称来创建(同Java)。例:let o = new Object();
- 如果构造函数没有参数,可以省略括号,合法但不推荐。
- 每个Object实例都有以下属性和方法:
- constructor:用于创建当前对象的函数。
- hasOwnProperty(propertyName):用于判断当前对象实例上是否存在给定的属性。
- isPrototypeOf(Object):用于判断当前对象是否为另一个对象的原型。
- propertyIsEnumerable(propertyName):用于判断给定的属性是否可以使用for-in语句枚举。
- toLocaleString():返回对象的字符串表示,该字符串反映对象所在的本地化执行环境。
- toString():返回对象的字符串表示。
- valueOf():返回对象对应的字符串、数值或布尔值表示。
- Object是所有对象的基类,所以任何对象都有这些属性和方法。
5.操作符
- 一元操作符
- 递增/递减操作符
- 同C语言
- 可以作用于任何值,整数,字符串,布尔值,浮点值甚至对象都可以。
- 一元加和减
- 同高中数学
- 应用到非数值时会执行于使用Number()转型函数一样的类型转换。
- 一元加(+)放到变量前头,对数值没有任何影响。
- 一元减(-)放在变量前头,主要用于把数值变成负值。
- 主要用于基本算数,也可用于数据类型转换。
- 递增/递减操作符
- 位操作符
- 在应用位操作时,在后台64位数值会转换为32位数值,然后执行位操作,最后再把结果从32位转换为64位存储起来。副作用是:特殊值NaN和Infinity在位操作中都会被当成0处理。
- 应用到非数值,首先会使用Number()函数将该值转换为数值。
- 按位非(~):返回数值的补数。
- 按位与(&)
- 按位或(|)
- 按位异或(^)
- 左移(<<):保留符号。
- 有符号右移(>>):保留符号
- 无符号右移(>>>)
- 布尔操作符
- 逻辑非(!)
- 返回值一定是布尔值。
- 首先将操作符转换为布尔值,然后对其取反。
- 同时使用两个叹号(!!),相当于调用了转型函数Boolean()。
- 规则:
如果操作数是对象,则返回false。
如果操作数是空字符串,则返回true。
如果操作数是非空字符串,则返回false。
如果操作数是数值0,则返回true。
如果操作数是非0 数值(包括Infinity),则返回false。
如果操作数是null,则返回true。
如果操作数是NaN,则返回true。
如果操作数是undefined,则返回true。
- 逻辑与(&&)
- 如果有操作数不是布尔值,返回值不一定是布尔值。
- 规则:
如果第一个操作数是对象,则返回第二个操作数。
如果第二个操作数是对象,则只有第一个操作数求值为true才会返回该对象。
如果两个操作数都是对象,则返回第二个操作数。
如果有一个操作数是null,则返回null。
如果有一个操作数是NaN,则返回NaN。
如果有一个操作数是undefined,则返回NaN。
- 逻辑或(||)
- 如果有操作数不是布尔值,返回值不一定是布尔值。
- 规则
如果第一个操作数是对象,则返回第一个操作数。
如果第一个操作数求值为false,则返回第二个操作数。
如果两个操作数都是对象,则返回第一个操作数。
如果两个操作数都是null,则返回null。
如果两个操作数都是NaN,则返回NaN。
如果两个操作数都是undefined,则返回undefined。
- 逻辑非(!)
- 乘性操作符:乘法、除法和取模。作用同Java,C语言。当操作数不是数值时,会在后台使用Number()转型函数转换为数值。
- 乘法(*)
- 操作符都是数值,执行常规乘法运算。如果不能表示乘积,则返回Infinity或-Infinity。
- 如果有任一操作数是NaN,则返回NaN。
- 如果是Infinity乘以0,则返回NaN。
- 如果是Infinity乘以非0的有限数值,则根据第二个操作数的符号返回Infinity或-Infinity。
- 如果是Infinity乘以Infinity,则返回Infinity。
- 如果不是数值的操作数,则先在后台用Number()将其转换为数值,然后再应用上述规则。
- 除法(/)
- 操作符都是数值,执行常规除法运算。如果不能表示商,则返回Infinity或-Infinity。
- 如果有任一操作数是NaN,则返回NaN。
- 如果是Infinity除以Infinity,则返回NaN。
- 如果是0除以0,则返回NaN。
- 如果是非0的有限值除以0,则根据第一个操作数的符号返回Infinity或-Infinity。
- 如果是Infinity除以任何值,则根据第二个操作数的符号返回Infinity或-Infinity。
- 如果不是数值的操作数,则先在后台用Number()将其转换为数值,然后再应用上述规则。
- 取模(%)
- 如果操作数是数值,则执行常规除法运算,返回余数。
- 如果被除数是无限值,除数是有限值,则返回NaN。
- 如果被除数是有限值,除数是0,则返回NaN。
- 如果是Infinity除以Infinity,则返回NaN。
- 如果被除数是有限值,除数是无限值,则返回被除数。
- 如果被除数是0,除数不是0,则返回0。
- 如果不是数值的操作数,则先在后台用Number()将其转换为数值,然后再应用上述规则。
- 乘法(*)
- 指数操作符:**
- 等价于Math.pow()
- 指数操作符也有自己的指数赋值操作符**=
- 加性操作符
- 加法操作符(+)
- 减法操作符(-)
- 关系操作符:都返回布尔值
- 小于(<)
- 大于(>)
- 小于等于(<=)
- 大于等于(>=)
- 相等操作符
- 等于(==)和不等于(!=):先进行类型转换,再确定操作数是否相等。
- 全等(===)和不全等(!==):比较相等时不转换操作数。
- 条件操作符:同Java中的三目运算符
variable = boolean_expression ? true_value : false_value;
- 赋值操作符
- 简单赋值(=)
- 复合赋值:使用乘性、加性或位操作符后跟等于号(=)表示
- 逗号操作符(,):可以用来在一条语句中执行多个操作
6.语句
- if语句:
if(condition) statement1 else statement2;
if(condition1) statement1 else if(condition2) statement2 else statement3;
- do-while语句
- while语句
- for语句:建议使用let声明迭代器变量
- for-in语句
- 建议使用const声明变量
for(const property in expression) statement;
- ECMAScript中对象的属性是无序的。因此for-in语句不能保证返回对象属性的顺序。
- for-of语句
- 一种严格的迭代语句,用于遍历可迭代对象的元素
for(property of expression) statement;
- 建议使用const声明迭代变量
- 会按照可迭代对象的next()方法产生值的顺序迭代元素
- 标签语句
- 用于给语句加标签,语法:label: statement
- 标签可以通过break或continue语句引用。(不太明白)
- break和continue语句
- break:立即退出循环,强制执行循环后的下一条语句。
- continue:立即退出循环,再次从循环顶部开始执行。
- 可以与标签语句一起使用,返回代码中特定的位置。(明白了)
- with语句
- 用途是将作用域设置为特定的对象,语法:
with(expression) statement;
- 主要场景是针对一个对象反复操作
- 严格模式不允许使用with语句,会抛出错误。
- 影响性能难调试,不推荐使用!
- 用途是将作用域设置为特定的对象,语法:
- switch语句(同Java)
7.函数
- 使用function关键字声明,后跟一组参数,然后是函数体。
function functionName(arg0,arg1,…,argN)
statements
- 使用函数名调用函数
- 不需要指定是否返回值,任何函数在任何时间都可以使用return语句来返回函数的值
- 不指定返回值的函数实际上会返回特殊值undefined
Java程序猿的JavaScript学习笔记(9—— jQuery工具方法)
计划按例如以下顺序完毕这篇笔记:
- Java程序猿的JavaScript学习笔记(1——理念)
- Java程序猿的JavaScript学习笔记(2——属性复制和继承)
- Java程序猿的JavaScript学习笔记(3——this/call/apply)
- Java程序猿的JavaScript学习笔记(4——this/闭包/getter/setter)
- Java程序猿的JavaScript学习笔记(5——prototype)
- Java程序猿的JavaScript学习笔记(6——面向对象模拟)
- Java程序猿的JavaScript学习笔记(7——jQuery基本机制)
- Java程序猿的JavaScript学习笔记(8——jQuery选择器)
- Java程序猿的JavaScript学习笔记(9——jQuery工具方法)
- Java程序猿的JavaScript学习笔记(10——jQuery-在“类”层面扩展)
- Java程序猿的JavaScript学习笔记(11——jQuery-在“对象”层面扩展)
- Java程序猿的JavaScript学习笔记(12——jQuery-扩展选择器)
- Java程序猿的JavaScript学习笔记(13——jQuery UI)
- Java程序猿的JavaScript学习笔记(14——扩展jQuery UI)
这是笔记的第9篇,从jQuery源代码的角度。聊聊jQuery的工具方法。
作者博客:http://blog.csdn.net/stationxp
作者微博:http://weibo.com/liuhailong2008
转载请取得作者允许
1、先看几个工具方法怎样使用:
var t = $.trim(' >>_<< '); var ps = $.param({x:15,y:16}); jQuery.type(function(){}) === "function"
jQuery的工具方法,相对jQuery本身,是相对独立的。
2、这些方法是怎样定义的呢?
我们推測一下,试试看。
我们知道jQuery(即$)是全局变量。这些方法应该是jQuery变量的属性。
我们能够通过例如以下语法加入:
jQuery.xx = function(a,b){ return a + b; } // try var r1 = jQuery.xx(2,3); console.log(r1);// output : 5 var r2 = $.xx(3,3); console.log(r2);// output : 6上面代码。说明$和jQuery引用了同样变量,他们是一样一样的。
这些代码达到了定义工具方法的目的,但jQuery是这样做的吗?
3、
查看jQuery源码。jQuery通过例如以下语法定义工具方法:
jQuery.extend({ noConflict: function( deep ) { if ( window.$ === jQuery ) { window.$ = _$; } if ( deep && window.jQuery === jQuery ) { window.jQuery = _jQuery; } return jQuery; } //, ... });
extend方法定义例如以下:
//定义了一个方法,赋值给jQuery.fn.extend和jQuery.extend. //jQuery.fn.extend和jQuery.extend尽管定义同样,但调用者不同,从而方法中this指向不同。从而实现的功能不同。 //没有显式声明參数,而是通过arguments动态获得,从而支持更丰富的功能。jQuery.extend = jQuery.fn.extend = function() { var src, copyIsArray, copy, name, options, clone, // 将第一个參数作为目标对象 target = arguments[0] || {}, // i初始化为1,临时还不知道做什么用 i = 1, // length表示參数的个数 length = arguments.length, // deep 应该表示是否深层拷贝,默觉得否。 deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { //假设第一个參数是布尔类型,则第二个參数为目标对象 //形如:jQuery.extend(false,UiObject,...); deep = target; target = arguments[1] || {}; // i 是当前參数的数组下标,从0開始 i = 2; } //目标对象是能是函数或者对象,传入其它參数,target默觉得空对象。
if ( typeof target !== "object" && !jQuery.isFunction(target) ) { target = {}; } // 眼下,假设第一个參数不是布尔。i值为1。length也为1,即extend(obj)的情况 // 假设是布尔,i值为2,length也为2,即extend(true,obj)的情况 // 总之。没有传入 src if ( length === i ) { // jQuery 把传入參数收了 // 參数下标又一次指向传入的这个參数,即此时指向了src target = this; --i; } // 如今i指向了target后面某个參数。应该是src // 把后面传入的每一个參数都当src for ( ;i < length; i++ ) { // Only deal with non-null/undefined values // 这样过滤非空啊,假设是undefined会被过滤掉吗? // 不做 typeof src 是否 "object"、"function"的推断吗? if ( (options = arguments[ i ]) != null ) { // 赋值给变量 options // Extend the base object for ( name in options ) { src = target[ name ]; copy = options[ name ]; // 思虑万全:假设已经是自家人,就别嘚瑟了 // Prevent never-ending loop if ( target === copy ) { continue; } // 对普通对象和数组。考虑递归深层拷贝 // 问题来了,什么叫普通对象? function 算不算? if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { if ( copyIsArray ) { // 设下次循环的默认值 copyIsArray = false; // 目标对象假设原来有这个属性。但不是数组类型。就被干掉了 clone = src && jQuery.isArray(src) ? src : []; } else { // 目标对象假设原来没有这个属性或者不是普通对象,默觉得{}。
// 假设已经有了并且是普通对象,那就用它了 clone = src && jQuery.isPlainObject(src) ? src : {}; } //递归调 //假设写成 jQuery.extend( deep, clone, copy ) 是否一样 // Never move original objects, clone them target[ name ] = jQuery.extend( deep, clone, copy ); // Don't bring in undefined values // 对 undefined 和 != null 还要加深理解 } else if ( copy !== undefined ) { // 临门一脚。假设是 jQuery.extend({xx,xfasf});的情况。扩展的是this,即调用者。
// 对target直接改动。也没创建clone啥的 target[ name ] = copy; } } } } // Return the modified object return target; };
4、再看看jQuery.isPlainObject怎样定义的
isPlainObject: function( obj ) { // Must be an Object. // Because of IE, we also have to check the presence of the constructor property. // Make sure that DOM nodes and window objects don't pass through, as well // 翻译: // 必须是一个对象。// 由于IE的缘故。我们还必须检查是否有constructor属性。
// 确认别放过Dom节点和window对象,他们不是普通对象。 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { // 下面不通过空、undefined、0、jQuery.type返回不是object的、dom对象、window对象 // 所以 typeof 为string、number、function、正则、date的都不成 return false; } try { // Not own constructor property must be Object if ( obj.constructor && !core_hasOwn.call(obj, "constructor") && !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { return false; } } catch ( e ) { // IE8,9 Will throw exceptions on certain host objects #9897 return false; } // 枚举的时候。自有属性会先被枚举出来。假设最后一个属性是自有属性。那么全部属性都是自有属性。 // 简而言之,不能有继承来的。能够被枚举到的属性,你妹。为什么有这种要求? // Own properties are enumerated firstly, so to speed up, // if last one is own, then all properties are own. var key; for ( key in obj ) {} return key === undefined || core_hasOwn.call( obj, key ); }
5、
试试看
jQuery.extend({ <span style="white-space:pre"> </span>sayHi:function(you){ <span style="white-space:pre"> </span>console.log('hi',you); <span style="white-space:pre"> </span>} }); $.sayHi('Stanley'); // output : hi Stanley
还不错!
假设想覆盖jQuery已有的方法呢?
jQuery.extend({ isPlainObject:function(obj){ return 'baby, I am not sure.'; } }); var r = $.isPlainObject({}); console.log(r); // output : baby, I am not sure.
这...好吧,能够得逞。想想别的办法吧,不能这样。
再玩儿:
jQuery.extend({ extend:function(obj){ // do nothing return 'who am i?'; } }); var r = $.extend({x:function(){ alert();}}); console.log(r); // output : who am i? jQuery.x();// error : function not be defined
又得逞,这样。再没人能够通过extend扩展jQuery的方法了。
但能够有更直接的方法。
以上是关于JavaScript学习笔记的主要内容,如果未能解决你的问题,请参考以下文章
Java程序猿的JavaScript学习笔记(9—— jQuery工具方法)
Java程序猿的JavaScript学习笔记(12——jQuery-扩展选择器)
JavaScript学习笔记(12)——JavaScript内置对象
JavaScript学习笔记——JavaScript语法之对象