众所周知,在js中对象就是精髓,不理解对象就是不理解js。

那么什么事js中的对象呢?

在js中,几乎一切皆对象:

  1. Boolean ,String,Number可以是对象(或者说原生数据被认作对象);
  2. Dates ,Maths,Regexps,Arrays,Funcitons,当然Objects,这些都是对象;

JS中,所有值,除了原生值,都是对象;这些原生值包括:strings,numbers('3.14'),true,false,null和undefined

对象是包含变量的变量,js变量可以包含单个值,比如:

var person = "John Doe";

 同样,对象也是变量,但它可以包含很多的值,只不过这些值是以键值对的形式表现的(name and value separated by a colon),一个js对象就是命名值的集合。

var person = {firstName:"John", lastName:"Doe", age:50, eyeColor:"blue"};

  对象属性

被命名的值,在js对象中被称为属性;这种以命名值而写的对象的写法类似于:

Property	Value
firstName John
lastName Doe
age 50
eyeColor blue
  • php的Associate Arrays
  • python中的Dictionaries
  • C中的Hash表
  • Java中的hash maps
  • Ruby和Perl中的Hashes

对象方法

方法是表现在对象上的行为或动作,对象属性可以是原生值,别的对象,或者函数。一个对象的方法是一个对象包含一个函数定义的属性。

fullName	function() {return this.firstName + " " + this.lastName;}

js对象是一个包含所谓属性的名值对和方法的容器。

创造一个js对象

在js中你可以定义和创造自己的对象,有不同的方法去创造对象:

  • 利用对象字面量
  • 利用new 关键字
  • 定义一个构造器,然后实例化
  • 在es5中,也可以利用Object.create()函数创造对象

对象字面量方法:最简单,一句话定义并创造一个对象。对象字面量是键值对用大括号抱起来的系列。

var person = {firstName:"John", lastName:"Doe", age:50, eyeColor:"blue"};

  new关键字方法:

var person = new Object();
person.firstName = "John";
person.lastName = "Doe";
person.age = 50;
person.eyeColor = "blue";

  以上两种例子几乎类似,没必要用new Object()。为了简洁,可读性及执行性能,首选第一种(对象字面量方法)。

对象构造器

以上两种方法在很多情境中有局限,它们只是创造一个单一对象。有时候,我们喜欢拥有一个可以创造很多一种类型对象的”对象类型“,此时利用对象构造函数创造一个对象类型的标准方式应运而生。

function person(first, last, age, eye) {
this.firstName = first;
this.lastName = last;
this.age = age;
this.eyeColor = eye;
}
var myFather = new person("John", "Doe", 50, "blue");
var myMother = new person("Sally", "Rally", 48, "green");

  以上方法是一个对象构造器,一旦拥有了它,你可以创造同类的对象

var myFather = new person("John", "Doe", 50, "blue");
var myMother = new person("Sally", "Rally", 48, "green");

This关键字

在js中,被称作this的东西,是一个“拥有”js代码的对象。this的值,当用在一个函数里,是一个”拥有“函数的对象;当用在一个对象里,是对象本身。this关键字,在一个对象构造器里边没本身有值,仅仅是新对象的替代品。当构造器被用于构造对象时this的值会变成新对象。

注意:this不是一个变量,它是关键字,你不能改变this值。

js用于内置的原生对象的构造器

var x1 = new Object();    // A new Object object
var x2 = new String(); // A new String object
var x3 = new Number(); // A new Number object
var x4 = new Boolean(); // A new Boolean object
var x5 = new Array(); // A new Array object
var x6 = new RegExp(); // A new RegExp object
var x7 = new Function(); // A new Function object
var x8 = new Date(); // A new Date object

  Math()对象不在列表中,因为Math是一个全局对象,new关键字不能用在Math中。

并且,众所周知,js拥有原生数据类型String,Number,和Boolean的对象版本。没理由创造浮躁对象,原生值执行的更快

var x1 = {};            // new object
var x2 = ""; // new primitive string
var x3 = 0; // new primitive number
var x4 = false; // new primitive boolean
var x5 = []; // new array object
var x6 = /()/ // new regexp object
var x7 = function(){}; // new function object

  JS对象是可变的

对象可变,他们靠索引定位而非值。如果一个person是一个对象,那么以下语句不会创造person的副本。

var x = person;  // This will not create a copy of person.

  对象x不是person的副本,它是person本身,因此任何x的改变都很改变person。

js变量不可变,可变(Mutable)的只是js对象,如下实例。

var person = {firstName:"John", lastName:"Doe", age:50, eyeColor:"blue"}

var x = person;
x.age = 10; // This will change both x.age and person.age

  对象属性

属性是js对象中最重要的部分

  • 属性是js对象所关联的值
  • js对象是无序属性的集合
  • 属性可以增删改查,有些是只读

访问js属性语法:

objectName.property          // person.age

objectName["property"]       // person["age"]

objectName[expression]       // x = "age"; person[x],表达式必须等于属性名

person.firstname + " is " + person.age + " years old.";
person["firstname"] + " is " + person["age"] + " years old.";

for-in循环遍历对象属性语法:

for (variable in object) {
code to be executed
}

 添加属性

person.nationality = "English";

  但你不能用保留字作为属性名,利用js命名规则。

删除属性

var person = {firstName:"John", lastName:"Doe", age:50, eyeColor:"blue"};
delete person.age; // or delete person["age"];

  删除关键字删除了属性值和其本身,删除后属性在其被再添加之前不能再用。删除操作符被用于对象属性的操作,对于变量或者方法无效。但谨记,delete操作符不应用于预定义js对象的属性,这样会阻塞应用。

属性的属性(property attributes)

属性有个name,也有一个value。value是属性的属性之一,其它属性是:enumerable,configurable,writable。这些属性定义了属性是如何被访问的(是否可读可写)

在js中,所有属性是可读的但只有value的属性可以被改变(当且仅当属性是可写的)。ES5中有针对getting和setting所有属性的属性的方法。

原型属性

js对象继承它们原型的属性,delete关键字不删除所继承的属性,但是如果你删除了原型的属性,这将影响所继承原型的所有对象。

对象方法

如前所述,js方法是对象中表现的行为。js方法是包含函数定义的属性,即方法是存做对象属性的函数。

访问对象方法:

methodName : function() { code lines }//创造一个对象方法

objectName.methodName();//访问
name = person.fullName();//fullName属性当以()调用时将执行
name = person.fullName;//fullName当么有()调用时将返回函数定义

  利用内置方法

var message = "Hello world!";
var x = message.toUpperCase();//HELLO WORLD!

  添加方法(类似于添加属性)

function person(firstName, lastName, age, eyeColor) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.eyeColor = eyeColor;
this.changeName = function (name) {
this.lastName = name;
};
}

  对象属性

所有js对象拥有一个原型(prototype),原型也是对象。所有js对象继承其原型的属性和方法。

利用字面量或者newObject 构造的对象,继承所谓的Object.prototype的原型;

利用new Date()构造的对象继承Date.prototype.Object.prototype 出于原型链的顶端(top)

因此所有的js对象继承自Object.prototype。

创造一个原型

标准方法是利用一个构造函数去创造一个对象原型:

function Person(first, last, age, eyecolor) {
this.firstName = first;
this.lastName = last;
this.age = age;
this.eyeColor = eyecolor;
}

  有了构造函数,你可以利用new关键字去从同样原型中创造新对象。

var myFather = new Person("John", "Doe", 50, "blue");
var myMother = new Person("Sally", "Rally", 48, "green");
//构造函数是Person对象的原型,首字母大写去命名构造函数是一个好惯例

  给对象添加属性和方法

有时你想添加新属性或方法给一个存在的对象,给所有给定类型的存在对象,或者给一个对象原型。

myFather.nationality = "English";//给一个存在的对象,仅仅对此对象

myFather.name = function () {
return this.firstName + " " + this.lastName;
};//添加一个方法,仅仅对此对象

  给原型添加属性

Person.nationality = "English";//不能像给已存在对象添加新属性那样给原型添加,因为原型不是一个存在的对象。

function Person(first, last, age, eyecolor) {
this.firstName = first;
this.lastName = last;
this.age = age;
this.eyeColor = eyecolor;
this.nationality = "English"
}//给原型添加属性,必须添加在构造函数里边。原型属性可以拥有原型值(默认值)
function Person(first, last, age, eyecolor) {
this.firstName = first;
this.lastName = last;
this.age = age;
this.eyeColor = eyecolor;
this.name = function() {return this.firstName + " " + this.lastName;};
}//添加方法

  利用原型属性

js原型属性允许你去给存在的原型添加新属性和新方法,但要记住:只改变你所拥有的属性,别去动标准js对象的属性。

function Person(first, last, age, eyecolor) {
this.firstName = first;
this.lastName = last;
this.age = age;
this.eyeColor = eyecolor;
}
Person.prototype.nationality = "English";
Person.prototype.name = function() {
return this.firstName + " " + this.lastName;
};

  js函数定义

js函数可以function关键字定义,你也可以用函数声明(declaration)和函数表达式( expression)去定义一个函数。

函数声明

function functionName(parameters) {
code to be executed
}
//分号被用于分离js执行语句,由于函数声明不是一个可执行语句,因此以分号结束一个函数声明并不常见

  函数声明不被立即执行,他们是“备用”,并且当调用时稍后执行。

函数表达式

var x = function (a, b) {return a * b};//函数表达式可以存储在一个变量里
var z = x(4, 3);//此时,这个变量可被用作一个函数
//事实上,上述函数是一个匿名函数,存储在变量中的函数不必拥有名字,他们用变量名调用;并且以分号结束是因为是可执行语句的一部分

函数构造器

函数可以利用js内嵌的函数构造器Function()定义

var myFunction = new Function("a", "b", "return a * b");
var x = myFunction(4, 3);

  事实上你不必如此,在js中很不必用到new关键字。

函数提升

提升是js移动声明到当前作用域顶端的默认行为,提升用于变量声明和函数声明,因此函数可以先调用后声明。但是,函数表达式定义的函数不会被提升。

myFunction(5);//25

function myFunction(y) {
return y * y;
}
foo();//VM747:1 Uncaught TypeError: foo is not a function(…)
var foo=function(){}

自执行函数

(function () {
var x = "Hello!!"; // I will invoke myself
})();

  事实上,上述函数是一个匿名的自执行函数

函数可被用在值中,也可用在表达式中

function myFunction(a, b) {
return a * b;
} var x = myFunction(4, 3);
var y= myFunction(4, 3) * 2;

  函数皆对象

typeof操作符在js中对于functions返回为‘function’,但是函数最好是被描述为对象,js函数拥有属性和方法。

function myFunction(a, b) {
return arguments.length;
}//但函数被调用时返回参数个数
var txt = myFunction.toString();//头String()方法返回一个字符串

  函数作为一个对象的属性定义,被称作一个对象的方法;

函数作为创造对象的定义,被称作一个对象构造器。

函数形参(parameters)

js函数对形参值不做任何检查。

js形参和实参:形参是函数定义中的名(names),实参是传给(或接收)函数的真实值(real values)

functionName(parameter1, parameter2, parameter3) {
code to be executed
}

  形参规则:js针对形参的函数定义不区分数据类型,对传来的实参不做类型检查,对接收的实参数目不做检查。

形参默认:如果函数丢失实参(少于声明的)时调用,缺失的值被设置为:undefined。有时候可以接受,但最好对形参设置一个默认值。

function myFunction(x, y) {
if (y === undefined) {
y = 0;
}
}//如果函数被过多实参(多余声明的)调用。这些实参可以利用实参对象获取

  实参对象

js拥有被称作实参对象的内置对象,它们包含一个实参数组,当函数被调用时。此时可以简单利用函数去在一个数据列表中寻找最值。

x = findMax(1, 123, 500, 115, 44, 88);

function findMax() {
var i;
var max = -Infinity;
for (i = 0; i < arguments.length; i++) {
if (arguments[i] > max) {
max = arguments[i];
}
}
return max;
}
//统计输入值之和
x = sumAll(1, 123, 500, 115, 44, 88); function sumAll() {
var i, sum = 0;
for (i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
return sum;
}

  按值传递的实参

形参,在函数调用中,就是函数实参;js实参按值传递,函数仅仅去知道值,而非实参地址。

如果一个函数改变了实参值,不会改变形参的原始值。形参的改变在函数外部不可见(不反映)。

对象按引用传递,js中对象索引是值,因此,对象表现为按索引传递:如果一个函数改变一个对象的属性,这就改变了原始值。对象属性的改变在函数外部可见(反映)

js函数调用

四种方式,每种方式以this如何初始化为区分。

函数调用:函数代码当定义时不执行,仅当调用时执行。(a JavaScript function can be invoked without being called.)

作为函数调用函数

function myFunction(a, b) {
return a * b;
}
myFunction(10, 2); // myFunction(10, 2) will return 20

  上述函数不属于任何对象,但js中有一个默认的全局对象。在html中默认的全局对象是html页面本身,因此上述函数”属于“html页面。在浏览器页面对象是浏览器窗口,上述函数自动变成window 函数,木Function和window.没有Function是一样的

这是一个常用的调用函数的方式,但并不是好习惯。全局变量,方法,或者函数在全局对象中很容易造成命名冲突和bug。

全局对象

当一个函数没有拥有者对象而被调用时,this值变成全局对象。在web浏览器中全局对象是browser window。

function myFunction() {
return this;
}
myFunction(); // Will return the window object

  调用一个作为全局对象的函数,引起让this值变为全局对象的后果。因此,用window对象作为变量很容易阻塞你的编程。

作为方法调用

作为方法调用

var myObject = {
firstName:"John",
lastName: "Doe",
fullName: function () {
return this.firstName + " " + this.lastName;
}
}
myObject.fullName(); // Will return "John Doe"

  fullName方法是一个函数,这个函数属于对象,没有Object是该函数的拥有者。被称作this的东西,是一个拥有js代码的对象,此时的this值指向myObject。

var myObject = {
firstName:"John",
lastName: "Doe",
fullName: function () {
return this;
}
}
myObject.fullName(); // Will return [object Object] (the owner object);将函数作为对象的方法来调用,使得this指向对象本身

  作为构造函数调用

如果一个函数以前置new关键字调用,他就是一个构造器的调用。看起来像创造一个新函数,但是由于js函数皆对象,你事实上创造了一个新对象。

// This is a function constructor:
function myFunction(arg1, arg2) {
this.firstName = arg1;
this.lastName = arg2;
} // This creates a new object
var x = new myFunction("John","Doe");
x.firstName; // Will return "John"

  构造器的调用创造了一个新对象,这个新对象继承他的构造器的属性和方法。this关键字在构造器中没有一个值,但是在构造器被调用时,this值将是所创造的那个新的对象。

以函数的方法调用

js中函数皆对象,js函数拥有属性和方法。call()和apply()是js的预定义函数方法,都可以调用函数,并且都必须将拥有者对象作为首个形参(调用时)。

function myFunction(a, b) {
return a * b;
}
myObject = myFunction.call(myObject, 10, 2); // Will return 20
function myFunction(a, b) {
return a * b;
}
myArray = [10, 2];
myObject = myFunction.apply(myObject, myArray); // Will also return 20

  两种方式均那拥有者对象(owner object)作为首个实参,唯一的区别是call分散地取函数实参,apply将函数实参作为一个数组来取。在js严格模式中,被调用的函数中首个实参是this的值,即使这个实参不是一个对象。在非严格模式中,如果首个实参是null或者undefined,它将被全局对象取代。利用call和apply你可以设置this值,并且将函数作为一个现有对象的方法调用。

js闭包

js变量可以属于全局的或者局部的作用域,局部变量可利用闭包构造。

全局变量

一个函数可以访问定义在其中的所有变量:

function myFunction() {
var a = 4;
return a * a;
}

  并且,一个函数也可以访问在其外层的函数,像这样:

var a = 4;
function myFunction() {
return a * a;
}

  此时a是一个全局变量,在页面中全局变量属于window对象,全局变量可被所有页面中脚本利用和改变;第一个例子中a是局部变量,局部变量仅能在其所定义的函数内部用,对其他函数和脚本代码隐藏。同名的全局和局部变量是不同的变量,改变一个不影响另一个,变量不以var关键字声明的通常是全局的,即使在函数内部。

变量生命周期

全局变量和你的应用程序,你的window,你的webpage同生,局部变量短命,当函数调用时被造就,当调用结束被删除。

看以下例子

var counter = 0;

function add() {
counter += 1;
} add();
add();
add(); // the counter is now equal to 3
function add() {
var counter = 0;
counter += 1;
} add();
add();
add(); // the counter should now be 3, but it does not work !
function add() {
var counter = 0;
function plus() {counter += 1;}
plus();
return counter;
}//solve this problem

  js闭包(closure)

还记得自我调用函数吗?这个函数干嘛的?

var add = (function () {
var counter = 0;
return function () {return counter += 1;}
})(); add();
add();
add(); // the counter is now 3

  解释:变量add作为一个自我调用函数的返回值声明,自执行函数仅运行一次,设置counter为0,返回表达式。这种方式的add变成一个函数,完美的部分是它可以访问父级作用域内的counter.这就是所谓的js闭包,它让函数拥有私有变量成为可能。counter被匿名函数的作用域所保护,并且只能利用add函数去改变。

总之:闭包是一个即使父级函数关闭,仍可以访问父级作用域的函数。

参考文献:http://www.w3schools.com/

JS中的对象和方法简单剖析的更多相关文章

  1. js中访问对象的方法

    如果在js中定义了一个变量obj1,如 var obj1 = 234; 那么访问这个边个两的方式至少有两种, 1 window["obj1"],那么值为234, 2 var tar ...

  2. JS高级面试题思路(装箱和拆箱、栈和堆、js中sort()方法、.js中Date对象中的getMounth() 需要注意的、开发中编码和解码使用场景有哪些)

    1.装箱和拆箱: 装箱:把基本数据类型转化为对应的引用数据类型的操作: var num = 123 // num var objNum = new Num(123) // object console ...

  3. JS中判断对象是不是数组的方法

    JavaScript中检测对象的方法 1.typeof操作符 这种方法对于一些常用的类型来说那算是毫无压力,比如Function.String.Number.Undefined等,但是要是检测Arra ...

  4. 深入理解JS中的对象(二):new 的工作原理

    目录 序言 不同返回值的构造函数 深入 new 调用函数原理 总结 参考 1.序言 在 深入理解JS中的对象(一):原型.原型链和构造函数 中,我们分析了JS中是否一切皆对象以及对象的原型.原型链和构 ...

  5. 浅解析js中的对象

    浅解析js中的对象 原文网址:http://www.cnblogs.com/foodoir/p/5971686.html,转载请注明出处. 前面的话: 说到对象,我首先想到的是每到过年过节见长辈的时候 ...

  6. js中判断对象具体类型

    大家可能知道js中判断对象类型可以用typeof来判断.看下面的情况 <script> alert(typeof 1);//number alert(typeof "2" ...

  7. JavaScript学习12 JS中定义对象的几种方式

    JavaScript学习12 JS中定义对象的几种方式 JavaScript中没有类的概念,只有对象. 在JavaScript中定义对象可以采用以下几种方式: 1.基于已有对象扩充其属性和方法 2.工 ...

  8. js中object的申明方法

    //js中的对象申明使用new Object(); //object类型的数据类似于数组通过下表来访问其中的值 //example1 var person=new Object(); person.n ...

  9. js中推断对象详细类型

    大家可能知道js中推断对象类型能够用typeof来推断. 看以下的情况 <script> alert(typeof 1);//number alert(typeof "2&quo ...

随机推荐

  1. E. Border

    E. Border time limit per test 1 second memory limit per test 256 megabytes input standard input outp ...

  2. JS判断内容为空方法总结

    HTML代码: 用户名:<input type="text" id="username"> <p style="color:red& ...

  3. [洛谷P2597] [ZJOI2012]灾难

    洛谷题目链接:[ZJOI2012]灾难 题目描述 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引 ...

  4. c版http服务器 shttpd-1.38 vs2013

    有个项目,本来是外网的.要做一个局域网版本. 项目启动就获取一大堆http的数据.考虑到可以提供http服务的软件虽然多,但是多要安装这样那样的软件,还要配置环境或者配置资源等问题. 发布的时候给人一 ...

  5. 省队集训Day1 睡觉困难综合征

    传送门:https://www.luogu.org/problem/show?pid=3613 [题解] 按二进制位分开,对于每一位,用“起床困难综合征”的方法贪心做. 写棵LCT,维护正反两种权值, ...

  6. 汕头市队赛 SRM19 字符题

    从天上掉下来了个这样的问题: 有一个字符串 从中选出两个子串 A,B,求 A+B可以构成的不同串的个数. 还想知道,这么多个串中字典序最大的那一个. 某人捡到了这个问题,并把它扔给了你. [输入] 一 ...

  7. 超详细的Java面试题总结(一)之Java基础知识篇

    面向对象和面向过程的区别 面向过程:   优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机.嵌入式开发.Linux/Unix等一般采用面向过程开发,性能是最重要的因 ...

  8. js按值及引用传递中遇到的小问题

    有人闲的蛋疼,非要在函数中使用如下方式传值,尼玛一下把我搞糊涂了.于是决定发挥打破沙锅问到底的精神搞清楚它. var a = 1,b = [], c = {}; function f(a, b, c) ...

  9. AndroidStudio 添加Selector文件,在res文件夹下添加文件夹

    在res文件夹下添加文件夹: 添加Selector文件:

  10. Bitmap算法应用实例(转)

    关于数据库查询工作,例如有如下数据库表 要想统计所有90后的程序员该怎么做呢?用一条求交集的SQL语句即可: Select count(distinct Name) as 用户数 from table ...