语言:程序最终被表达为数据(结构)和逻辑(算法),命令式和说明式/函数式语言分别从这两方面分类;
动态:在语言陈述时无法确定,必须在计算机执行时才能确定语言关系;JS是完全动态语言,导致其不确定性一般包括:
- 标识符确定:表现为动态类型,动态重写,动态存取数据结构;
- 语句上下文确定:表现为动态变量/语法作用域,闭包作用域;
起源:
- 动态数据类型:
- 动态类型声明(动态类型绑定):语言变量是无类型的,只有在赋值后才有某种类型;
- 动态空间分配(动态数据绑定):变量在赋值时才会分配空间;
- 动态执行系统:
- 编译器:将代码翻译成计算机可以理解的二进制代码;
- 解释器:解释执行的语言系统,之后用一个执行环境读入并执行这份代码;
- 动态执行系统一般依赖于解释和及时编译系统;目前JS一般采用虚拟执行环境+即使编译系统+语言引擎;
动态执行: //动态执行系统分别动态加载和动态执行;JS中动态执行主要是eval()带来的效果;
动态方法调用:
- JS中的执行体:
- eval()函数入口指定的字符串,该字符串总是被作为当前函数上下文的语句来执行;
- new Function()中传入的字符串,该字符串总是被作为一个全局,匿名函数闭包中的语句行被执行;
- 执行体就是一个函数,通过()来执行;
- 指定this对象: //call,apply,bind
function calc_area(w, h) { console.log(w * h); } function Area() { this.name = 'MyOject'; } Area.prototype.doCalc = function() { calc_area.apply(this,arguments); } var area = new Area(); area.doCalc(10,20); //200 Area.prototype.doCalc = function(v1) { var slice = Array.prototype.slice; calc_area.apply(this,[v1*2].concat(slice.call(arguments,1))) } area.doCalc(10,20); //400
- 栈的可见与修改:
function func_1() {}; function func_2() { func_1.apply(this,arguments); } func_2();
如上,在func_1.apply()被调用时,arguments被做了一次复制,值数值被复制,引用数据被创建引用,所以其实func_1与func_2中操作的arguments是两套数据;但是可以这样进行修改:
function func_1() { arguments.callee.caller.arguments[0] = 100; }
- bind() //bind方法绑定的函数做构造函数构造出来的对象即是绑定后的函数的实例,也是绑定前函数的实例;
重写://JS的重写是一个代码执行期的行为,语法分析期时引擎不会做任何预期或限制;其可能的问题是在运行期中会发现冲突或因为错误意外重写导致不可预料的代码逻辑错误;
- 原型重写: //无法保证JS中,对象和其构造器必然存在某种相似性;其实重写原型已经违背了面向对象系统的基本原则;所以原型重写会导致同一个构造器可能有多套原型系统;
function MyOject_0() {} var obj_1 = new MyOject_0(); MyOject_0.prototype = { constructor: MyOject_0 } var obj_2 = new MyOject_0(); console.log(obj_1 instanceof MyOject_0); //false console.log(obj_2 instanceof MyOject_0); //true
- 构造器重写:
//执行期,重写变量 function MyObject_2() {}; var obj1 = new MyObject_2; MyObject_2 = function() {}; var obj2 = new MyObject_2; console.log(obj2 instanceof MyObject_2); //true console.log(obj1 instanceof MyObject_2); //false //语法分析期,标示符覆盖 function MyObject_3() {}; var obj1 = new MyObject_3; function MyObject_3() {}; var obj2 = new MyObject_3; console.log(obj2 instanceof MyObject_3); //true console.log(obj1 instanceof MyObject_3); //true