javascript对象是通过引用来传递的,它们永远不会被拷贝.
尝试获取javascript对象的某个属性值,且该对象没有此属性名,那么javascript会试着从原型对象中获取属性值。如果那个原型 对象也没有该属性,那么再从他的原型中寻找,依次类推,直到该过程最后到达终点 Object.prototype . 如果想要的属性完全不存在于原型链中, 那么結果就是 undefined 值。这个过程称为委托.
确定属性的类型
typeof flight.number //'number'
typeof flight.status //'string'
typeof flight.arrival //'object'
typeof flight.manifest //'undefined'
如果对象拥有独有的属性, hasOwnProperty(‘attribute’)返回 true, 此方法不会检查原型链
直接使用 for in
使用 typeof 和 hasOwnProperty() 来过滤掉不想要的属性
删除对象中的属性不会影响到原型对象中的属性, 但是会使原型对象中的属性暴露出来(因为属性委托机制)
obj.nickname //'nick name in object'
delete obj.nickname
obj.nickname //'nick name defined in prototype'
有两种方法减少全局变量污染:
在javascript中,函数就是对象. 对象是”名/值”对的集合并拥有一个连接到原型对象的隐藏连接.
对象字面量产生的对象连接到 Object.prototype . 函数对象连接到 Function.prototype (该原型对象本身连接到Object.prototype)
!! 每个函数在创建时附有两个隐藏属性: 函数上下文 和 实现函数行为的代码.
函数与众不同的之处最它们可以被调用
函数字面量的创建:
通过函数字面量创建的函数包含有一个连接到外部上下文的连接,这被称为闭包
闭包是javascript强大表现力的根基
函数被调用时会接收两个参数: this 和 arguments, 其中 this 的值取决于调用的模式.
(传入参数包含this与python的对象方法非常的类似,只不过javascript不需要形参来显式接收this, 而python强制要求第一个形参接收传入的this引用(按惯例,这个引用一般叫self)
javascript的this引用是javascript之所以如此灵活的根基(我是这样想的), 利用this可以实现方法的高度复用.
四种方法调用模式:
方法调用模式
当一个函数被保存为对象的一个属性时,我们称它为一个方法(看来方法与函数还是有区别的). 当方法被调用时, this 被绑定到该对象. this到对象的绑定发生在调用的时候,这个超级迟绑定(very late binding)使得函数可以对this高度利用. 通过 this可取得它们所属对象的上下文的方法被称为公共方法.
函数调用模式
当一个函数并非一个对象的属性时,那么它被当作一个函数来调用. 当函数以此模式被调用时, this被绑定到全局对象– 这是语言设计的一个错误.这个错误设计的后果就是方法不能利用内部函数来帮助它工作, 因为内部函数的this被绑定了错误的值, 所以不能共享该方法对对象的访问权.
可以通过 that = this 来解决 (命令为that是约定)
构造器调用模式
(曾经是我最常用的一种方式, 现在看来我错了很久...) 一种模糊了javascript原型本质的,类似基于类的语言的对象构建语法, 一种两边不讨好的语法. (a. 模糊了原型本质 b. 不伦不类的基于类的对象构造语法)
按照约定, 构造器首字母要大写.
new 前缀创建出一个空白对象, 把这个空白对象作为构造器函数的this引用传入, 在构造器函数内对这个对象进行一些操作.
function Person(){
var name = 'steven';
var age = '24';
this.getPersonInfo = function(){
return name + '-' + age;
};
this.sayHi = function(){
print('hello, ' + this.getPersonInfo());
}
}
var person = new Person();
print(person.getPersonInfo());
这种形式没有使用原型继承, 全部都是方法的复制, 每个新创建的对象都从构造器函数中一份完全相同的属性值, 增大了系统开销.
不推荐这种调用模式
apply 模式
javascript函数隐式传入this引用正是为apply调用模式服务的. 调用形式: functionName.apply(objectReference, arguemnts) 以objectReference为引用, arguments为函数去执行functionName函数.
call与apply功能相同,不同之处是apply以数组形式给函数传入参数,而call将多个参数一一例举出来传递.
var sum = add.apply(null,[2, 3]);
var sum2 = add.call(null,2,3);
函数中的arguments可以获取传给函数的所有参数, 但是arguments的实现是又一个javascript语言实现的错误, arguments只是一个类数组(array-like), 拥有length属性, 但是缺少所有的数组方法
javascript函数总会返回一个值,如果没有明确使用return语句,则返回undefined.
javascript可以使用throw语句抛出一个异常(是一个对象直接量), 异常对象会传递给 catch 子句.
给类型添加方法(修改类型对象的原型)
Number.prototype.add = function(){ return this + arguments[0]; } print((2).add(5)); // 7
function级别的作用域. 在一个function内部定义的变量在function内部的任何地方都可见.
闭包: 一个函数字面量持有外部的上下文环境. 上下文环境指的是, 外部函数中定义的变量和外部函数接收的参数.
闭包的常见写法:
一般形式:
(jQuery链式写法全是级联), 级联操作的每个方法返回 this 而不是 undefined
函数也是值,从而我们可以用有趣的方式来操作函数值. 套用允许我们将函数与传递给它的参数相结合去产生一个新的函数.
Object.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
}
Function.method('curry', function(){
// args represents arguemnts pass to curry function
// that represents the original function object
var slice = Array.prototype.slice;
var args = slice.apply(arguments), that = this;
//using closure to keep above value
return function() {
var param = slice.apply(arguments).concat(args);
that.apply(null, param );
}
});
function add() {
print(arguments[0] + arguments[1]);
return arguments[0] + arguments[1];
}
var addWith1 = add.curry(1);
addWith1(6); // 7