这周天气开始回暖,课上大家都很犯困,可能是讲的内容比较晦涩难懂吧
一、函数
1)模仿块级作用域
- 自调用函数
- 写法
(function(){})()
(function(){}())
- 沙箱模式模仿块级作用域
function outputNumbers(count){
(function(){
for(var i=0; i< count; i++){
console.log(i)
}
})()
console.log(i) // 报错
}
在外部环境中无法访问沙箱环境中的任何数据,但是由于在沙箱中this指向全局,故可以修改外部的数据
2)递归
- 典型递归
function factorial(num){
if(num <= 1){
return 1
}else {
return num * factorial(num -1)
}
}
- 使用callee实现
function factorial(num){
if(num <= 1){
return 1
}else {
return num*arguments.callee(num-1)
}
}
- 解耦函数名,隔离
var factorial = (function f(num){
if(num <= 1){
return 1;
}else {
return num * f(num-1)
}
})
3)闭包
- 引用外部数据
function foo(name){
return function(){
console.log(name)
}
}
** 导致数据被缓存,无法释放
- 利用闭包解决引用问题
function createFunction(){
var result = new Array();
for(var i=0; i<10; i++){
result[i] = function (num){
return function(){
return num; // 引用num 导致num无法释放
}
}(i)
}
return result;
}
- 闭包产生的this 指向问题
var name = 'The window';
var obj ={
name: 'my obj',
getNameFunc: function(){
return function(){
return this.name
}
}
}
console.log(obj.getNameFunc()()) // The window
// 导致this指向全局的原因: 每个函数在被调用时都会自动取得两个特殊变量this和arguments ,
// 内部函数在搜索这两个变量的时候,只会搜索到其活动对象为止
4)私有变量
- 模块模式
var singleton = function (){
var privateVariable = 10;
function privateFunc(){
return false;
}
// 创建对象
var object = new CustomType();
// 特权,公有方法和属性
object.publicProperty = true;
object.publicMehod = function(){
privateVariable++;
return privateFunc()
}
return object;
}()
此方法,内部的私有变量和方法得以保护,外界无法通过singleton变量访问
二、面向对象
1)属性类型
- 数据属性
* Configurable 是否可配置
* Enumerable 是否可枚举
* Writable 是否可修改
* Value 属性的数据值
- 修改属性的默认特性
var o = {};
Object.defineProperty(o,'name',{
value: '中国',
writable: false
})
o.name = '美国'
console.log(o.name)
- 访问器属性
var book ={
_year: 2001,
edition: 1
};
Object.defineProperty(book, 'year',{
get: function(){
return this._year
},
set: function(newVal){
if(newVal > this._year){
this._year = newVal;
this.edition += newVal - 2001;
}
}
})
book._year = 2002;
console.log(book.edition)
console.log(book._year)
调用 get 和 set 两个存取器方法 ,能够限制修改属性的值
- 定义多个属性的特性
var o2 = {}
Object.defineProperties(o2,{
_year: {
writable:true,
value: 2004
},
edition: {
writable: true,
value: 1
},
year: {
get: function(){},
set: function(){}
}
})
- 读取属性的特性
var descriptor = Object.getOwnPropertyDescriptor(book,"year")
2)创建对象
构造函数 + 原型模式
function Mode(name, age, job){
this.name = name;
this.age = age;
this.job = job;
}
Mode.prototype = {
constructor: Mode,
sayName: function(){
console.log(this.name)
}
}
var mode = new Mode('Nick', 30, 'software')
- in 操作符 判断是否是可访问的属性
var o5 = {
name: '张三'
}
console.log("name" in o5)
- for-in 遍历所有可访问的属性
function Animal(name){
this.name
}
Animal.prototype.size = 23;
var animal = new Animal('狮子')
animal.sex = '公'
for(var prop in animal){
console.log(prop)
}
- Object.keys()
console.log(Object.keys(animal))
返回所有可枚举的实例属性的一个字符串数组, 不会遍历到原型上
- Object.getOwnPropertyNams
console.log(Object.getOwnPropertyNames(Animal.prototype))
此方法用于获取所有实例的属性,不管是否可枚举
3)继承
- 组合继承
组合继承 首先会使用对象冒充的方式去继承父类构造函数中的属性,接着通过对子类的prototype.constructor
设置进行构造器校正。
function SuperType(name){
this.name = name;
this.colors = ['red','blue','green']
}
SuperType.prototype.sayName = function(){
console.log(this.name)
}
function SubType(name,age){
//继承属性
SuperType.call(this, name);
this.age = age;
}
// 继承方法
SubType.prototype = new SuperType()
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge= function(){
console.log(this.age)
}
- 寄生组合式继承
function inheritPrototype(subType,superType){
var prototype = Object.create(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
function SuperType(name){
this.name = name;
this.colors = ['red','blue','green']
}
SuperType.prototype.sayName = function(){
console.log(this.name)
}
function SubType(name,age){
SuperType.call(this,name);
this.age = age;
}
inheritPrototype(SubType,SuperType);
var subtype = new SubType('张三', 23)
subtype.sayName(); // 张三