javascript 面向对象二

1.javaScript删除某个对象的属性,方法

 

var bingo1 = {}; 
bingo1.shouts = 'hey!';
bingo1.hello = function()
{
    console.log('hello');
};
 
//删除bingo1对象的属性shouts
delete bingo1.shouts;   

//删除bingo1对象的方法hello,这里不能写成delete bingo1.hello(),它会调用bingo1.hello()
delete bingo1.hello;   
bingo1.hello();
console.log(bingo1.shouts);

 

 

2.函数分类:一般函数 和 匿名函数

 

一般函数(有指定函数名doSomethingCool) 

 

function doSomethingCool()
{
    console.log('I do something mindblowingly cool');
}

 


匿名函数(没有指定函数名)


function ()
{
    console.log('My parents forgot to name me!');
};
 

 

 
function doSomethingCool()
{
    console.log('I do something cool');
}
 
//现在makeSomeNoise和doSomethingCool两个对象都引用了相同的函数 doSomethingCool()
var makeSomeNoise = doSomethingCool;
 
//调用doSomethingCool函数,输出的是I do something cool
doSomethingCool();
 
//分配doSomethingCool函数名(实际也是个对象)指向另一个不同的函数
doSomethingCool = function()
{
    console.log('I do something hot');
}
 
//再次调用doSomethingCool函数,输出则是I do something hot,与上面不同
doSomethingCool();

 

3函数的调用

 

// 通常的方式
function boring(msg)
{
    console.log( msg);
}
 
boring('The usual way');
 
 
//通常的方式-- 匿名形式
A
(function cool(msg){
    console.log( msg);
 })('The unusual way - anonymously');
 
B
 
var usefulStuff = (function makeUsefulStuff(){
    var bingo={desc:'My name is Bingo'};
    return bingo;
})();
//这里运用这种调用方式,立即调用makeUsefulStuff()函数返回bingo赋给了usefulStuff


 

 



 

 

4.构造函数

 

function Employee()
{
    console.log('Employee function');
};
 
var emp1 = new Employee();

当你调用使用new关键字的函数时,在运行时会创建一个空对象,并将该对象传递到这函数,该对象就变成了在这函数内this的值;

一旦完成其执行的函数,该函数将自动返回一个引用到this,即使你在函数的末尾显式地编写一个返回语句.

注意,如果你的调用的函数没有new关键字,它就没有创建新对象,例如调用 Employee()函数,它就不会返回一个引用到this

而是如果函数有显示地编写返回语句,就返回该语句的内容,因为这里Employee()没有,所以没有返回什么内容.

 

 

Object对象的结构如下:


 



function Employee()
{
    console.log('Executing Employee function');
};
 
var emp1 = new Employee();
var dummy = {};
var hello = new Object();
 
console.log(dummy.constructor);      //a
console.log(hello.constructor);         //b
console.log(emp1.constructor);       //c

 

结果输出的是:


Executing Employee function 
function Object() { [native code] } 
function Object() { [native code] } 
function Employee()
{
    console.log('Executing Employee function');
}


因为dummy和hello实际都是Object,所以a 和 b实际上调用的都是Object的constructor属性,可以从Object的结构图看出constructor的结构.

而c则输出了自身Employee对象的构造函数来

 


由于函数本身也是Object(对象),所以函数也应当拥有构造函数,如下:

 

function Employee()
{
    console.log('Executing Employee function');
}
console.log(Employee.constructor);
console.log((function noname(){}).constructor);
console.log(Function.constructor);

 

 

结果输出的是:

function Function() { [native code] } function Function() { [native code] } function Function() { [native code] }

这里说明的Employee()函数的构造函数是function Function() { [native code] }

匿名函数的构造函数是function Function() { [native code] }

Function本身的构造函数也是function Function() { [native code] }

 

 

this关键字与函数的上下文

 

function outerFunc()
{
    console.log('outer ' + this);
    function innerFunc()
    {
        console.log('inner ' + this);
    }
    innerFunc();
}
outerFunc();


输出的是如下:

outer [object Window] 
inner [object Window]

因为调用outerFunc()没有指定它是属于哪个Object(对象)上,

那么javaScript认为它是属于window对象上的,实际上等价于window.outerFunc().

 

 

 

var bingo = {};
bingo.outerFunc=function()
{
    console.log('outer ' + this);
    function innerFunc()
    {
        console.log('inner ' + this);
    }
    innerFunc();
};
bingo.outerFunc();

 

结果输出的是:

 

outer [object Object] 
inner [object Window] 

由于调用bingo.outerFunc()中,指定了outerFunc()所属的为bingo对象上的,它实际也是个Object,所以outer中输出的this为outer [object Object]

而inner中输出的this则为[object Window] ,这暗示上下文context并没有继承,即当函数A定义在另一个函数B内,并在函数B内调用,在函数A内是没有继承函数B(outer function外部函数)的this

 

 


var myHappyObject =
{
    name : 'MrHappy',
    rename : function (name)
    {
        this.name = name;
        console.log(this.name);
    }
};
 
var duplicateReference = myHappyObject.rename; 
 
myHappyObject.rename('myHappyObject');
console.log(window.name);     //a
duplicateReference('window');
console.log(window.name);     //b

 

结果输出的是:

myHappyObject
(空字符串)
window
window

首先执行var duplicateReference = myHappyObject.rename;将duplicateReference引用指向了函数renam即

rename : function (name)   

{

       this.name = name;

       console.log(this.name);

}

由于调用duplicateReference('window');没有给它指定明确的对象,所以javaScript认为它属于window对象,即

调用的是window.duplicateReference('window'),接着它进入rename函数中,执行this.name = name,这时

this指向的正式window,所以它为window对象添加了不必要的属性name,并将它赋值为‘window’值,这一点可以从

输出结果看出,首先执行a时,输出的window.name为‘空字符串’.而最后执行b时则输出了‘window’,可见执行

duplicateReference('window');就是为window对象添加属性name并赋值为‘window’.

 

 

 

5.闭包

function printer(msg)
{
    function printMe()
    {
        console.log(msg);
    }
    return printMe;
}
var p = printer('first');
var b = printer('second');
 
p();
b();

 

结果输出为:

 

first 
second

这里p和b引用的都是相同的函数-printMe,因为它们都调用printer,printer函数最终返回printMe内部函数的引用.

虽然它们引用相同的函数printMe,但是结果输出的却不相同(一般如果引用相同的函数在这里输出会相同),这是为什么?

 

这是因为虽然外部函数printer()执行完毕,内部函数printMe()仍然保留着外部函数printer()的变量状态的一个隐藏的引用,

在上面,因为msg是外部函数printer()的一个局部变量,而且我们一直保留着内部函数printMe()的引用,

所以外部函数printer()的局部变量msg的生命周期一直保留着,所以输出的是不同的.

 

如果您可以 保存 内部函数 引用,您可以人为地增加 外部函数的一个局部变量 的生命周期

 

 

 

var holder = {};
holder.outer =function (name)
{
    this.name=name;
    //保存outer的this到that以便inner可以用
    var that = this;
    console.log('Outer name : ' + name);
 
    function inner(){
        console.log("Inner Name : " + that.name);
    };
 
    return inner;
};
 
var p = holder.outer('Popeye');
p();

 

输出的结果为:

 

Outer name : Popeye 
Inner Name : Popeye

那么如果你想在inner内部函数内利用outer外部函数的this来实现一些功能的话,

你可以把this封装在一个闭包变量,如上面的var that = this;然后就可以在inner使用that.name

 

 

 

function helloWorld()
{
    if(1)
    {
        var a = 76;
    }
    console.log(a);
}
helloWorld();
 

输出的结果为:76

在javaScript中一个变量的作用域范围是在它声明所在的整个函数中,

所以上面虽然是在if中声明var a变量,但是还是能在 helloWorld()函数内if外中访问该变量a

 

 

 

 

var n = 1;
function someRandomFunction()
{
 
    console.log(n);   //输出undefined 
    var n = 100; 
    console.log(n);   //输出100
}
someRandomFunction();

 

输出的结果为:

undefined
100 

为什么第一个会输出undefined呢?不是在someRandomFunction()函数外已经声明了var n = 1吗?

出现这种奇怪的行为原因是javaScript存在一个功能叫做hoisting(“提升”)

 

即对于在任何作用域范围内声明的变量、JavaScript会分离变量声明和变量的初始化,

将变量的声明放置到该作用域范围内的第一行,而变量的初始化则还是放置到程序员初始化的位置中.

所以上面的函数等价于

var n = 1;
function someRandomFunction()
{
    var n;               //变量的声明隐藏在这里
    console.log(n); //所以这里输出undefined,因为上一行只是声明变量n,还没初始化 
    n = 100;           //现在变量n被初始化
    console.log(n); //这里输出了100
}
someRandomFunction();

 

 

//undefined
function someRandomFunction()
{
   var n;
    console.log(n);
}
 
//undefined
function someRandomFunction()
{
   console.log(n);
   var n;
}

 

函数调用顺序注意

usual();
function usual()        //a形式
{
    console.log('function defined in usual way')
}
 
variable();
var variable = function()    //b形式
{
    console.log('function defined in variable way');
};

 

结果输出为:

function defined in usual way 
Uncaught TypeError: Property 'variable' of object [object Window] is not a function

说明函数定义用通常的形式即a形式,可以在函数定义前就调用它usual(); 

而b形式的定义方式是不能在函数定义之前就去调用它的,它会报错,因此最好都是在函数定义后再去调用该函数.

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值