一、认识对象
如何判断是否是对象? 能添加属性值。
- 狭义对象
所谓狭义对象就是{}形式定义的对象,它是一组属性的无序集合。对象是键值对,既有值,也有语义。
var obj = {
name:"小明",
age:12,
sex:"男",
hobby:["游戏","编程"]
}
对象就是一组值和值得语义的封装
- 广义对象
除了可以有属性还有其他东西,有一个dom元素在页面上
var o = document.getElementById("box");
alter(typeof o);// object
o.sex = 22;
o.name = "小红";
系统内置的所有引用类型值都是对象,都能添加自定义属性。
- function 函数
- array 数组
- regexp 正则表达式
- DOM 元素
- window、document、Math、Date
- Number、String 等内置包装构造函数得到的值
- 什么不是对象
var a = 100;
a.age = 12;
alert(a.age); //undefined
var s = "哈哈";
s.age = 12;
alert(a.age); //undefined
基本类型值,字面量不是对象
number,string,boolean,undefined,null
二、对象和 JSON 的区别
JSON 就是 javascript object notation,JS对象表示法,是JS对象的严格子集。
JSON要求所有的键必须加双引号,而JS对象实际上不要求加双引号。
// JSON格式
var obj1 = {
"name": "小明",
"age": 12,
"sex": "男"
}
//js对象 不严格要求双引号
var obj2 = {
name: "小明",
age: 12,
sex: "男",
}
但是有一种情况js对象的键必须加引号!
就是不符合标识符命名规范的键,必须加引号,否则报错。
//合法
var obj = {
$ : 12,
_ : 13 ,
_$0_0$_: 14
}
//不合法,需加双引号,取值时需 obj["2016"] 中括号+引号调用
// 命名规则如下
//1.由字母、数字、$、_组成
//2.以字母、$、_开头
//3.不可以使用保留字!!!
var obj = {
"-":12,
"@@@":13,
"2016":12,
"哈哈":15
}
三、对象的方法
如果一个对象的属性值是一个函数,我们称这个属性叫做这个对象的方法(methods)
var obj = {
name: "小明",
age: 12,
sex: "男",
sayHello: function(){
alert("你好");
}
}
四、函数的上下文(context)
- 函数上下文是什么?
函数的上下文其实就是函数里this的指向。
- 函数this指向谁?,或者说函数上下文是谁?
函数的上下文是谁?,取决于函数如何调用,而不是函数如何定义(定义的位置)。
函数的上下文是函数的调用时表现的性质,不是函数定义的时候写死的性质。(换句话说,就是函数不调用时,无法判断函数上下文是谁)
var obj = {
name: "小明",
age: 12,
sex: "男",
sayHello: function(){
alert("你好"+this.name+",年龄是"+this.age+"岁");
}
}
obj.sayHello();
var fn = obj.sayHello;
fn();
var name = "小红";
var age = 22;
fn();
- 函数的上下文六大规律
规律1:函数直接圆括号调用,函数的上下文是window对象
(所有的全局变量都是window对象的属性,而函数内部的变量是局部变量,不是window的属性,也不是这个函数的属性)
//例子1
function fn(){
var a = 666;
alert(this.a);
}
var a = 777;
fn();
//例子2
var a = 777;
function fn(){
var a=666;
var ff = function(){
alert(this.a);
}
ff();
}
fn();
规律2:函数如果作为一个对象的属性,被对象打点调用,那么函数的上下文就是这个对象
var obj = {
name: "小明",
age: 12,
sex: "男",
sayHello: function(){
alert("你好"+this.name+",年龄是"+this.age+"岁");
}
}
obj.sayHello();
规律3:函数是事件处理函数,函数的上下文就是触发此事件的对象
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style>
.box{
width: 100px;
height: 100px;
background: black;
margin: 10px;
}
</style>
</head>
<body>
<div class="box" id="box1"></div>
<div class="box" id="box2"></div>
<div class="box" id="box3"></div>
<script src="js/jquery-3.2.1.js"type="text/javascript" ></script>
<script>
function fn (){
this.style.background = "red";
}
var box1 = document.getElementById("box1");
var box2 =document.getElementById("box2");
var box3 =document.getElementById("box3");
box1.onclick = fn;
box2.onclick = fn;
box3.onclick = fn;
</script>
</body>
</html>
规律4:定时器调用函数,函数的上下文是window对象
//例1
function fn(){
alert(this.aa);
}
var aa = 66666;
setInterval(fn,2000);
//例2
function fn(){
alert(this.aa);
}
var aa = 66666;
setInterval(function(){
fn(); //这种可看为规律1,结果一样指向window
},2000);
//例3
document.getElementById("box1").onclick = function(){
setInterval(function(){
this.style.background = "red";
},1000);
};
//正例
document.getElementById("box1").onclick = function(){
var self = this;
setInterval(function(){
self.style.background = "red";
},1000);
};
规律5:数组中存放的函数,被数组通过索引直接圆括号调用,那么这个函数的上下文就是这个数组
function fn(){
console.log(this);
alert(this[2]);
}
var arr = [fn,"EZ","盖伦"];
arr[0]();
五、构造函数
- new运算符
function Person(){
alert("aaa");
}
new Person(); //弹出aaa
通过上述例子我们可以看出new 运算符会调用函数。
function Person(){
this.name = "小明";
this.age = 12;
}
var obj = new Person();
alert(obj.name);//弹出小明
通过上述例子可以看出 new 运算符调用函数会执行哪些操作?
- 新建一个空对象{}
- 将函数的this指向这个空数组
- 执行函数体内容
- 执行完毕后,retrun 返回刚才创建的对象
function Person(name,age){
this.name = name;
this.age = age;
}
var xiaoming = new Person("小明",12);
var xiaohong = new Person("小红",22);
console.log(xiaoming);
console.log(xiaohong);
我们改造一下,发现JS的这种构造函数,很像JAVA里的类对象了。
我们可以认为Person是一个 “类”,而 xiaoming,xiaohong就是这个类的 “实例”。
六、原型链
![](https://img.haomeiwen.com/i10489903/21de0b57423f0605.png)
_proto_ 是神器,具有原型链查找功能,当在xiaoming实例身上找不到某属性的时候,会沿着proto去原型对象上查找是否有这个属性。
//例
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype = {
teacher : "流浪法师",
zhishang: 180
}
var xiaoming = new Person("小明",12);
var xiaohong = new Person("小红",22);
alert(xiaoming.teacher);
alert(xiaohong.teacher);
可以看一下jQuery 的源码,如何运用原型链,做一些巧妙的设计。
最经典的就是jQuery的无new构造,不需要繁琐的new $("input") ,只需要$("input")即可获得实例。
(function(window, undefined) {
var
// ...
jQuery = function(selector, context) {
// The jQuery object is actually just the init constructor 'enhanced'
// 看这里,实例化方法 jQuery() 实际上是调用了其拓展的原型方法 jQuery.fn.init
return new jQuery.fn.init(selector, context, rootjQuery);
},
// jQuery.prototype 即是 jQuery 的原型,挂载在上面的方法,即可让所有生成的 jQuery 对象使用
jQuery.fn = jQuery.prototype = {
// 实例化化方法,这个方法可以称作 jQuery 对象构造器
init: function(selector, context, rootjQuery) {
// ...
}
}
// 这一句很关键,也很绕
// jQuery 没有使用 new 运算符将 jQuery 实例化,而是直接调用其函数
// 要实现这样,那么 jQuery 就要看成一个类,且返回一个正确的实例
// 且实例还要能正确访问 jQuery 类原型上的属性与方法
// jQuery 的方式是通过原型传递解决问题,把 jQuery 的原型传递给jQuery.prototype.init.prototype
// 所以通过这个方法生成的实例 this 所指向的仍然是 jQuery.fn,所以能正确访问 jQuery 类原型上的属性与方法
jQuery.fn.init.prototype = jQuery.fn;
})(window);
网友评论