时间:2021-05-26
讲解还是以示例代码搭配注释的形式,这里做个小目录:
JS代码预解析原理(包括三个段落);
函数相关(包括 函数传参,带参数函数的调用方式,闭包);
面向对象(包括 对象创建、原型链,数据类型的检测,继承)。
JS代码预解析原理
复制代码 代码如下:
/****************** JS代码预解析原理 ******************/
// 下边给出 三段觉得比较典型的代码示例:
/********** 一:基本的几条语句 **********/
alert(num); // undefined
var num = 0;
alert(str); // 错误:str未定义
str = "string";
alert(func); // undefined
var func = function (){ alert('exec func'); }
test(); // exec test
alert(test()); // 先exec test 后undefined
function test(){ alert('exec test'); }
/********** 二:函数名与变量名相同 **********/
//var mark = 1;
function mark(x) {
return x * 2;
}
var mark;
alert(mark); // function mark(x) { return x * 2; }
// 去掉前边的var mark = 1;则会返回1
/********** 三:把第二段包括在语句块中 **********/
// 当有条件时候(代码包含在条件语句块里)
if (false) {
var mark1 = 1;
function mark1() {
alert("exec mark1");
}
//var mark1;
alert(mark1);
}
alert(mark1);
mark1();
// 由于解析浏览器解析不同,这段代码在不同浏览器里执行的结果不一致,具体原因可从网上查找答案
函数相关(包括 函数传参,带参数函数的调用方式,闭包)
复制代码 代码如下:
/****************** 函数相关 ******************/
/********** 一:函数传参 **********/
var yx01 = new function() {return "圆心"};
alert(yx01); // [object Object]
var yx02 = new function() {return new String("圆心")};
alert(yx02); // “圆心”
/********** 二:数据类型的检测 **********/
/***** 1、通过constructor属性 *****/
var myvar= new Array("a","b","c","d");
function A(){}
myvar.constructor = A;
var c = myvar.constructor;
alert(c); // function A(){}
//可见,通过constructor属性获取类型的方法很容易被修改,不应该用来判断类型。
/***** 2、通过typeof *****/
var num = new Number(1);
var arr = [1,2,3];
alert(typeof num); //object 而不是number
alert(typeof arr); //object 而不是Array
alert(typeof null); // object
/***** 3、通过 instanceof *****/
function t(){};
t.prototype = Array.prototype;
//t.prototype = [];
var x = new t();
alert(x instanceof t);//弹出true
alert(x instanceof Array);//弹出true
alert(x instanceof Object);//弹出true
/***** 4、通过 Object.prototype.toString.call() *****/
var num = new Number(1);
var arr = [1,2,3];
alert(Object.prototype.toString.call(num)); // [object Number]
alert(Object.prototype.toString.call(arr)); // [object Array]
// 扩展示例:(apply等价于call)
window.utils = {
toString: Object.prototype.toString,
isObject: function (obj) {
return this.toString.apply(obj) === '[object Object]';
},
isFunction: function (obj) {
return this.toString.apply(obj) === '[object Function]';
},
isArray: function (obj) {
return this.toString.apply(obj) === '[object Array]';
}
}
function A() { }
window.utils.isFunction(A); //true
window.utils.isObject(new A()); //true
window.utils.isArray([]); //true
/********** 三:继承 **********/
(function () {
// initializing变量用来标示当前是否处于类的创建阶段,
// - 在类的创建阶段是不能调用原型方法init的
// - 我们曾在本系列的第三篇文章中详细阐述了这个问题
// fnTest是一个正则表达式,可能的取值为(/\b_super\b/ 或 /.*/)
// - 对 /xyz/.test(function() { xyz; }) 的测试是为了检测浏览器是否支持test参数为函数的情况
// - 不过我对IE7.0,Chrome2.0,FF3.5进行了测试,此测试都返回true。
// - 所以我想这样对fnTest赋值大部分情况下也是对的:fnTest = /\b_super\b/;
var initializing = false, fnTest = /xyz/.test(function () { xyz; }) ? /\b_super\b/ : /.*/;
// 基类构造函数
// 这里的this是window,所以这整段代码就向外界开辟了一扇窗户 - window.Class
this.Class = function () { };
// 继承方法定义
Class.extend = function (prop) {
// 这个地方很是迷惑人,还记得我在本系列的第二篇文章中提到的么
// - this具体指向什么不是定义时能决定的,而是要看此函数是怎么被调用的
// - 我们已经知道extend肯定是作为方法调用的,而不是作为构造函数
// - 所以这里this指向的不是Object,而是Function(即是Class),那么this.prototype就是父类的原型对象
// - 注意:_super指向父类的原型对象,我们会在后面的代码中多次碰见这个变量
var _super = this.prototype;
// 通过将子类的原型指向父类的一个实例对象来完成继承
// - 注意:this是基类构造函数(即是Class)
initializing = true;
var prototype = new this();
initializing = false;
// 我觉得这段代码是经过作者优化过的,所以读起来非常生硬,我会在后面详解
for (var name in prop) {
prototype[name] = typeof prop[name] == "function" &&
typeof _super[name] == "function" && fnTest.test(prop[name]) ?
(function (name, fn) {
return function () {
var tmp = this._super; // 这里是必要的,第91行注释代码可说明之。
this._super = _super[name];
var ret = fn.apply(this, arguments);
this._super = tmp;
return ret;
};
})(name, prop[name]) :
prop[name];
}
// 这个地方可以看出,Resig很会伪装哦
// - 使用一个同名的局部变量来覆盖全局变量,很是迷惑人
// - 如果你觉得拗口的话,完全可以使用另外一个名字,比如function F()来代替function Class()
// - 注意:这里的Class不是在最外层定义的那个基类构造函数
// 这里的Class和上边的window.Class函数不一样,这里是window.Class内部的函数局部变量
function Class() {
// 在类的实例化时,调用原型方法init
if (!initializing && this.init)
this.init.apply(this, arguments);
}
// 子类的prototype指向父类的实例(完成继承的关键)
Class.prototype = prototype; // Class指代上边的Class,并非一开始的window.Class
// 修正constructor指向错误
// 是否可用Class.prototype.constructor = Class;来修正???
Class.constructor = Class;
// 子类自动获取extend方法,arguments.callee指向当前正在执行的函数
Class.extend = arguments.callee;
return Class;
};
})();
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
案例知识点:1.vue.js基础知识2.HTML5本地存储localstoragestore.js代码constSTORAGE_KEY='todos-vue.j
(推荐)JS正则知识点专题:https://www.jb51.net/article/139831.htmfunctionstripscript(s){retu
首先需要一个带输入表格.复制代码代码如下:Insert知识点知识点答案需要js来处理提交数据到服务器上以及从服务器获取提交后的返回数据.submit.js代码如
复制代码代码如下:/***知识点1:ListViewitem:两种长按弹出菜单方式*知识点2:ListViewSimpleAdapter的使用*知识点3:在ja
在讲replace的高级应用之前,我们先简单梳理一下JS正则中的几个重要的知识点,以帮助你对基础知识的回顾,然后再讲解JS正则表达式在replace中的使用,以